Расширение стандартных полей ресурса через свою таблицу в MODX

Александр Мальцев
Александр Мальцев
18.8K
59
Расширение стандартных полей ресурса через свою таблицу в MODX
Содержание:
  1. Добавление таблицы в базу данных
  2. Создание директории для компонента
  3. Создание XML схемы компонента
  4. Генерирование модели компонента
  5. Принцип работы с компонентом extendresource
  6. Представление расширенных полей ресурса в админке
  7. Как добавить checkbox поле к компоненту и отобразить его в админке
  8. Как в админке MODX создать поля с одиночным и множественным выбором из списка
  9. Комментарии

Статья, в которой рассмотрим способ добавления дополнительных полей к ресурсу без использования TV.

Для хранения дополнительных данных будем использовать не системную (site_content), а свою таблицу. Например, имеющую имя site_content_extend. Для обеспечения работы с ней посредством xPDO создадим компонент (рабочую модель). В качестве названия компонента выберем, например, extendresource.

Для представления дополнительных полей в админке, а именно на страницах создания и редактирования ресурсов, напишем плагин. Если вам это действие не нужно, то создание этого элемента можно опустить.

Добавление таблицы в базу данных

Добавление новых объектов в базу данных можно осуществить, например, с помощью инструмента phpmyadmin.

В качестве примера создадим таблицу site_content_extend, имеющую следующие поля:

  • id – характеристики: тип - int(10), атрибуты – unsigned, auto_increment – да, первичный;
  • resource (id ресурса) – характеристики: тип - int(10), атрибуты – unsigned, уникальный;
  • views (количество просмотров) - характеристики: тип - int(10), атрибуты – unsigned, по умолчанию - 0;
  • keywords (ключевые слова) - характеристики: тип - varchar(120), по умолчанию – пустая строка;
  • level (минимальный уровень доступа к ресурсу) - характеристики: тип - smallint(5), атрибуты – unsigned, по умолчанию - 0.
Добавление таблицы в базу данных с помощью инструмента phpmyadmin

SQL дамп таблицы «modx_site_content_extend» можно скачать по этой ссылке.

Создание директории для компонента

Создадим в директории /core/components каталог extendresource.

После этого создадим ещё несколько папок, чтобы получился следующий путь:

core/components/extendresource/model/schema/

Создание XML схемы компонента

В каталоге schema компонента extendresource поместим файл extendresource.mysql.schema.xml со следующим содержимым:

<?xml version="1.0" encoding="UTF-8"?>
<model package="extendresource" baseClass="xPDOObject" platform="mysql" defaultEngine="MyISAM" version="1.1">
  <object class="extendResource" table="site_content_extend" extends="xPDOSimpleObject">
    <field key="resource" dbtype="int" precision="10" attributes="unsigned" phptype="integer" null="false" index="unique" />
    <field key="views" dbtype="int" precision="10" attributes="unsigned" phptype="integer" null="false" default="0" index="index" />
    <field key="keywords" dbtype="varchar" precision="120" phptype="string" null="false" default="" />
    <field key="level" dbtype="smallint" precision="5" attributes="unsigned" phptype="integer" null="false" default="0" />

    <index alias="resource" name="resource" primary="false" unique="true" type="BTREE">
      <column key="resource" length="" collation="A" null="false" />
    </index>
    <index alias="views" name="views" primary="false" unique="false" type="BTREE" >
        <column key="views" length="" collation="A" null="false" />
    </index>

    <aggregate alias="Resource" class="modResource" local="resource" foreign="id" cardinality="one" owner="foreign" />
  </object>
</model>

XML схема в MODX Revolution – это описание объектов базы данных компонента и их связей. Она нужна только для того, чтобы выполнить генерацию рабочей модели компонента.

Генерирование модели компонента

На этом шаге создадим модель. Для выполнения этого действия воспользуемся скриптом parse_schema.php.

Принцип работы со скриптом parse_schema.php:

  1. Открыть файл в текстовом редакторе и ввести название компонента.
  2. Положить его в корень MODX сайта.
  3. Открыть данный файл из браузера.

После выполнения скрипта в каталоге «core/components/extendresource/model/» будут созданы php файлы (модель компонента).

MODX Revolution – Ввод название компонента в утилиту parse_schema.php MODX Revolution – Открытие файла parse_schema.php из браузера

Принцип работы с компонентом extendresource

Примеры, в которых показано, как можно осуществить получение значений расширенных полей ресурса и сохранение данных в них.

Сохранение данных в расширенные поля ресурса

Фрагмент php-кода, который можно использовать в сниппете или плагине для установки значений расширенным полям ресурса (views, keywords, level):

$id = $modx->resource->get('id');
$extendResource = $modx->getObject('extendResource',array(
  'resource' => $id,
));
if (!is_object($extendResource)) {
  $extendResource = $modx->newObject('extendResource');
  $extendResource->set('resource', $id);
}
$extendResource->set('views', 77);
$extendResource->set('keywords', 'modx, создание сайтов');
$extendResource->set('level', 100);
$extendResource->save();

Получение значений расширенных полей ресурса

Вывод значений расширенных полей ресурса на страницу можно осуществить разными способами.

1 вариант - с помощью плагина (например, ExtendResource).

Код плагина ExtendResource (php):

<?php
$modx->addPackage('extendresource', $modx->getOption('core_path').'components/extendresource/model/');

// в каких ресурсах необходимо показывать расширенные поля (массив шаблонов)
// $templateIds = [2, 3]; // (1)

// получаем шаблон, установленный в системных настройках по умолчанию
// $templateId = $modx->getOption('default_template'); // (1)
// получаем контекст нового ресурса
// $contextKey = $_GET['context_key'];

// если ресурс не новый, то получаем шаблон у ресурса
if ($id > 0) {
//   $templateId = $resource->get('template'); // (1)
//   $contextKey = $resource->get('context_key');
}

// если дополнительные поля нужно вывести только в ресурсах, привязанных к шаблонам указанных в $templateIds (в этом случае строчки (1) нужно раскомментировать)
// if (!in_array($templateId, $templateIds)) { // (1)
//  return; // (1)
// } // (1)

$id = $modx->resource->get('id');
$views = 0;
$keywords = '';
$level = 0;
// если ресурс не новый, то...
if ($id > 0) {
  $extendResource = $modx->getObject('extendResource',array(
    'resource' => $id,
  ));
  if (is_object($extendResource)) {
    $views = $extendResource->get('views');
    $keywords = $extendResource->get('keywords');
    $level = $extendResource->get('level');
  }
}
// устанавливаем плейсхолдеры
$modx->setPlaceholders(array(
  'views' => $views,
  'keywords' => $keywords,
  'level' => $level
),'extend.');
return;

В качестве события, при котором будет происходить выполнения плагина, установим OnLoadWebDocument. Данное событие возникает после загрузки документа, но перед тем как теги MODX будут обработаны.

Основное действие плагина ExtendResource заключается в установке плейсхолдеров extend.views, extend.keywords и extend.level.

Вывод значений расширенных полей текущего ресурса (в чанке или шаблоне):

Просмотры: [[+extend.views]]
Ключевые слова: [[+extend.keywords]]
Уровень: [[+extend.level]]

Другой вариант получить значения дополнительных полей – это воспользоваться сниппетом (например, getExtendResource):

<?php

$array = array (
  'views' => 0,
  'keywords' => '',
  'level' => 0
);

$output = $array[$field];

$id = $modx->resource->get('id');
$extendResource = $modx->getObject('extendResource',array(
  'resource' => $id,
));
if (is_object($extendResource)) {
    $output = $extendResource->get($field);
}

return $output;

Использование сниппета getExtendResource для получения значения расширенных полей ресурса (например, keywords):

[[!getExtendResource? &field=`keywords`]]

Представление расширенных полей ресурса в админке

Для того чтобы представить расширенные поля ресурса на страницах создания и редактирования ресурса, необходимо создать плагин (например, ExtendedResource). Плагин будет выполнять действия, при наступлении 2 событий: OnDocFormPrerender и OnDocFormSave. Поэтому на странице создания плагина во вкладке «Системные события» необходимо установить галочки напротив них.

MODX Revolution – Установка событий, которые должен отслеживать этот плагин

Событие OnDocFormPrerender возникает перед тем, как в менеджере будет загружена форма редактирования ресурса. Данное событие будем использовать для добавления расширенных полей views, keywords и level в форму создания и редактирования ресурса.

Событие OnDocFormSave происходит после того, как ресурс будет сохранён в менеджере через форму редактирования. Данное событие будем использовать для сохранения значений расширенных полей views, keywords и level.

Данный плагин (ExtendedResource) нужен только для того, чтобы с данными полями можно было взаимодействовать при создании и редактирования ресурсов в админке. Если это вам не нужно, то этот плагин можно не добавлять в систему MODX Revolution.

<?php

$modx->addPackage('extendresource', $modx->getOption('core_path').'components/extendresource/model/');

/* при необходимости */
// в каких ресурсах необходимо показывать расширенные поля (массив шаблонов)
// $templateIds = [2, 3];

// получаем шаблон, установленный в системных настройках по умолчанию
// $templateId = $modx->getOption('default_template');
// получаем контекст нового ресурса
// $contextKey = $_GET['context_key'];
// если ресурс не новый, то получаем шаблон и контекст у ресурса
// if ($id > 0) {
//   $templateId = $resource->get('template');
//   $contextKey = $resource->get('context_key');
// }

// завершаем работу плагина, если шаблон ресурса не соответствует не одному из указанных
// if (!in_array($templateId, $templateIds)) {
//   return;
// }

switch ($modx->event->name) {
  // OnDocFormPrerender
  case 'OnDocFormPrerender':
    $views = 0;
    $keywords = '';
    $level = 0;
    // если ресурс не новый, то...
    if ($id > 0) {
      $query = $modx->newQuery('extendResource');
      $query->where(array(
        'resource' => $id,
      ));
      $extendResource = $modx->getObject('extendResource',$query);
      if (is_object($extendResource)) {
        $views = $extendResource->get('views');
        $keywords = $extendResource->get('keywords');
        $level = $extendResource->get('level');
      }
    }
    $modx->controller->addHtml("<script>
    Ext.ComponentMgr.onAvailable('modx-resource-main-right', function(page) {
      page.on('beforerender', function() {
        page.insert(2,{
          xtype: 'textfield'
          ,name: 'views'
          ,value: {$views}
          ,anchor: '100%'
          ,layout: 'anchor'
          ,fieldLabel: 'Просмотры'
        });
        page.insert(3,{
          xtype: 'textfield'
          ,name: 'level'
          ,value: {$level}
          ,anchor: '100%'
          ,layout: 'anchor'
          ,fieldLabel: 'Уровень'
        });
      })
    });
    Ext.ComponentMgr.onAvailable('modx-resource-main-left', function(page) {
      page.on('beforerender', function() {
        page.insert(2,{
          xtype: 'textfield'
          ,name: 'keywords'
          ,value: '{$keywords}'
          ,anchor: '100%'
          ,layout: 'anchor'
          ,fieldLabel: 'Ключевые слова'
        });
      })
    });
  </script>");
    break;
  // OnDocFormSave
  case 'OnDocFormSave':
    $id = $scriptProperties['resource']->get('id');
    $query = $modx->newQuery('extendResource');
    $query->where(array(
      'resource' => $id,
    ));
    $extendResource = $modx->getObject('extendResource',$query);
    if (!is_object($extendResource)) {
      $extendResource = $modx->newObject('extendResource');
      $extendResource->set('resource', $id);
    }
    $extendResource->set('views', $_POST['views']);
    $extendResource->set('keywords', $_POST['keywords']);
    $extendResource->set('level', $_POST['level']);
    $extendResource->save();
    break;
}
MODX Revolution – Отображение расширенных полей на страницах создания и редактирования ресурсов

Как добавить checkbox поле к компоненту и отобразить его в админке

Процесс добавления checkbox поля к компоненту и представление его в админке состоит из следующих шагов:

1. Добавить в таблицу site_content_extend, например, поле isquestion. Характеристики: тип - tinyint(1), атрибуты – unsigned, по умолчанию – 0.

Добавление поле в таблицу базы данных, которое в MODX будет представлять checkbox поле

2. Обновить XML схему компонента, т.е. добавить в неё описание этого поля:

<field key="isquestion" dbtype="tinyint" precision="1" attributes="unsigned" phptype="boolean" null="false" default="0" />

3. Перегенерировать модель компонента с помощью скрипта parse_schema.php.

4. Обновить плагин ExtendedResource:

<?php
//...
$isquestion = 0;
//...
$isquestion = $extendResource->get('isquestion');
//...
page.insert(4,{
  xtype: 'xcheckbox'
  ,boxLabel: 'Отметье, если это вопрос'
  ,name: 'isquestion'
  ,id: 'extendresource-isquestion'
  ,inputValue: 1
  ,checked: parseInt({$isquestion}) || false
});
...
$extendResource->set('isquestion', $_POST['isquestion']);
Как добавить checkbox в админку MODX

Как в админке MODX создать поля с одиночным и множественным выбором из списка

В этом примере создадим 2 поля. Первое поле – это size. Заполнение этого поля в админке организуем из выпадающего списка с возможностью выбора только одного значения. Второе поле – это myhobbies. Данные этого поля могут состоять из нескольких значений устанавливаемых из списка.

Основные шаги:

1. Добавим в таблицу site_content_extend 2 поля.

  • Характеристики поля size: тип - varchar(5), сравнение – utf8_general_ci, по умолчанию – пустая строка.
  • Характеристики поля myhobbies: тип - varchar(255), сравнение – utf8_general_ci, по умолчанию – пустая строка.
Таблица компонента MODX

2. Добавим эти поля в XML схему компонента extendresource:

<field key="size" dbtype="varchar" precision="5" phptype="string" null="false" default="" />
<field key="myhobbies" dbtype="varchar" precision="255" phptype="string" null="false" default="" />

3. Обновим модель компонента, для этого запустим на выполнение уже настроенный скрипт parse_schema.php.

4. Добавим в плагин ExtendedResource код, который предоставит возможность работать с этими полями в админке MODX:

...
$size = '';
$myhobbies = '';
...
$size = $extendResource->get('size');
$myhobbies = $extendResource->get('myhobbies');
...
page.insert(5,{
  xtype: 'extendresource-size'
  ,name: 'size'
  ,value: '{$size}'
  ,hiddenName: 'size'
  ,anchor: '100%'
  ,layout: 'anchor'
  ,fieldLabel: 'Размер'
});
page.insert(6,{
  xtype: 'extendresource-myhobbies'
  ,id: 'extendresource-myhobbies-id'
  ,resizable: true
  ,name: 'myhobbies[]'
  ,hiddenName: 'myhobbies[]'
  ,value:'{$myhobbies}'
  ,anchor: '100%'
  ,layout: 'anchor'
  ,fieldLabel: 'Мои увлечения'
});
...
MODx.combo.extendresourceSizes = function(config) {
config = config || {};
Ext.applyIf(config,{
  store: new Ext.data.ArrayStore({
    id: 0
    ,fields: ['size']
    ,data: [
      ['XS']
      ,['S']
      ,['M']
      ,['L']
    ]
  })
  ,mode: 'local'
  ,displayField: 'size'
  ,valueField: 'size'
});
MODx.combo.extendresourceSizes.superclass.constructor.call(this,config);
};
Ext.extend(MODx.combo.extendresourceSizes,MODx.combo.ComboBox);
Ext.reg('extendresource-size',MODx.combo.extendresourceSizes);

MODx.combo.extendresourceMyhobbies = function(config) {
config = config || {};
Ext.applyIf(config,{
  xtype:'superboxselect'
  ,triggerAction: 'all'
  ,mode: 'local'
  ,store: new Ext.data.ArrayStore({
    id: 0
    ,autoLoad: true
    ,fields: ['hobbies']
    ,data: [
      ['бег']
      ,['дайвинг']
      ,['плавание']
      ,['лыжи']
      ,['боулинг']
    ]
  })
  ,mode: 'local'
  ,displayField: 'hobbies'
  ,valueField: 'hobbies'
  ,forceSelection: true
  ,triggerAction: 'all'
  ,extraItemCls: 'x-tag'
  ,expandBtnCls: 'x-form-trigger'
  ,clearBtnCls: 'x-form-trigger'
});
MODx.combo.extendresourceMyhobbies.superclass.constructor.call(this,config);
};
Ext.extend(MODx.combo.extendresourceMyhobbies,Ext.ux.form.SuperBoxSelect);
Ext.reg('extendresource-myhobbies',MODx.combo.extendresourceMyhobbies);
...
$extendResource->set('size', $_POST['size']);
$extendResource->set('myhobbies', implode(',', $_POST['myhobbies']));
...
Создание в админке MODX списка с одиночным выбором Создание в админке MODX списка с множественным выбором

Комментарии: 59

  1. Павел Андросов
    Павел Андросов
    01.02.2021, 17:44
    Александр, здравствуйте. В админку все вывелось, но вот в таблицу данные не сохраняются. При перезагрузке — скидывается до данных по умолчанию. Скорее всего — я не добавил код для сохранения данных. Не могли бы вы поподробнее рассказать как сделать сохранение данных. Спасибо
    1. Александр Мальцев
      Александр Мальцев
      02.02.2021, 16:07
      Здравствуйте! Может забыли включить системное событие OnDocFormSave для плагина?
    2. Павел Андросов
      Павел Андросов
      02.02.2021, 16:26
      Проблема была в создании классов из схемы. Видимо, указал неправильную схему в parse_schema.php. Теперь все работает, огромное спасибо за уроки :)
  2. Александр
    Александр
    30.11.2020, 21:54
    Александр, доброго вечера Вам! Случайно обнаружил «опечаток» в руководстве а точнее в разделе где рассказывается за плагин: «ExtendedResource» а конкретно в этой строке:
    </script>HTML);
    при таком окончании скрипта, выходит вот эта ошибка:
    Parse error: syntax error, unexpected '' (T_ENCAPSED_AND_WHITESPACE), expecting '-' or identifier (T_STRING) or variable (T_VARIABLE) or number (T_NUM_STRING)
    если каждый тег перенести на новую строку, всё работает:
    </script>
    HTML
    );
    Интересно, почему так происходит?
    1. Александр Мальцев
      Александр Мальцев
      01.12.2020, 14:49
      Привет, Александр! Спасибо, так получилось при форматировании кода статьи. Изменил этот момент, а также дополнительно вынес определение этой строки и присвоил её переменной $html. Так мне кажется лучше.
      Это просто такой синтаксис в php для определения строк. Он называется heredoc.
    2. Александр
      Александр
      02.12.2020, 02:11
      Здравствуйте! Внёс изменения в плагин, спасибо.
  3. Александр
    Александр
    28.11.2020, 21:05
    Александр, здравствуйте! Пытаюсь добавить условие для ограничения вывода своих полей, чтобы вывод полей был только в тех ресурсах у которых id шаблона равен 3 и 4, отчасти получается, но как обычно есть проблемы которые не получается решить, делаю так:
    if(!in_array($resource->get('template'),[3,4])){break;}
    почему-то это условие работает только для ресурсов, которые уже созданы а если добавляешь новый ресурс, то поля выводятся не смотря на то, какой шаблон у ресурса находится в поле (Шаблон), расскажите пожалуйста, как нужно сделать, чтобы при добавлении нового ресурса, поля выводились только в том случае, если в поле (Шаблон) выбран шаблон с id которые указаны в условие?
    1. Александр Мальцев
      Александр Мальцев
      29.11.2020, 16:51
      Добрый вечер! Эту возможность добавил в код плагина, приведённый в статье. По умолчанию этот код закомментирован. Раскомментируйте и внесите id нужных шаблонов в $templateIds.
    2. Александр
      Александр
      29.11.2020, 18:52
      Здравствуйте! Александр, огромнейшее спасибо за решение, очень нужный функционал.
  4. Александр
    Александр
    27.11.2020, 23:30
    Александр, доброго вечера Вам! Попал на глаза опечаток в руководстве, где рассказано за плагин «ExtendedResource» в место пакета: «extendresource» указан класс:
    modx->addPackage('extendResource'
    на локалке так работает, без проблем, видимо не так чувствителен к регистру а на хосте уже не хочет.
    1. Александр Мальцев
      Александр Мальцев
      29.11.2020, 14:34
      Спасибо, Александр! Поправил. Не работало, т.к. название пакета не соответствовало имени папки «extendresource». В Windows имена каталогов и файлов просто не чувствительны к регистру, а в остальных системах это конечно уже будут разные элементы.
  5. Amsterdam
    Amsterdam
    15.11.2020, 14:44
    Александр, добрый день!

    А как можно в minishop2, из карточки товара на фротне, записать определенную информацию в новое отдельное поле и потом вывести ее в админке? Этим способом почему то у меня не получается у товаров вывести доп.поля. Может где то ошибся, или там нужно по другому что то делать?..
    1. Александр Мальцев
      Александр Мальцев
      18.11.2020, 14:01
      Привет! Нужно проверить, где-то что-то забыли сделать. В админке проблем не должно быть. С фронта наверно не получится, т.к. ms2form работает дополнительно только с TV. Тут скорее всего только своё писать.
  6. Александр
    Александр
    14.11.2020, 04:23
    Александр, здравствуйте! Как можно в админке вывести поле «изображение», подскажите пожалуйста?
    1. Александр Мальцев
      Александр Мальцев
      18.11.2020, 15:31
      Привет!
      Можно так:
      page.insert(1,{
        xtype: 'panel'
        ,border: false
        ,bodyStyle: 'margin-top: 10px;'
        ,html: '<img src="/assets/img-1.png" style="max-width: 100%; height: auto;">'
      });
      
    2. Александр
      Александр
      18.11.2020, 21:39
      Здравствуйте! Спасибо. Александр, скажите пожалуйста а как можно добавить своё поле, для добавления изображения к ресурсу?
    3. Александр Мальцев
      Александр Мальцев
      27.11.2020, 15:04
      Привет! Вставить поле для добавления изображения к ресурсу, используя Ext JS можно так (посредством modx-combo-browser):
      // ...
      page.insert(0,{
        xtype: 'modx-combo-browser'
        ,fieldLabel: 'Изображение'
        ,name: 'image'
        ,id: 'image'
        ,anchor: '100%'
        ,layout: 'anchor'
      });
      // ...
      MODx.combo.Browser = function(config) {
        config = config || {};
        Ext.applyIf(config,{
          width: 400
         ,triggerAction: 'all'
         ,triggerClass: 'x-form-file-trigger'
         ,source: config.source || MODx.config.default_media_source
        });
        MODx.combo.Browser.superclass.constructor.call(this,config);
        this.config = config;
      };
      Ext.extend(MODx.combo.Browser,Ext.form.TriggerField,{
        browser: null
       ,onTriggerClick : function(btn){
          if (this.disabled){
            return false;
          }
          this.browser = MODx.load({
            xtype: 'modx-browser'
           ,closeAction: 'close'
           ,id: Ext.id()
           ,multiple: true
           ,source: this.config.source || MODx.config.default_media_source
           ,hideFiles: this.config.hideFiles || false
           ,rootVisible: this.config.rootVisible || false
           ,allowedFileTypes: this.config.allowedFileTypes || ''
           ,wctx: this.config.wctx || 'web'
           ,openTo: this.config.openTo || ''
           ,rootId: this.config.rootId || '/'
           ,hideSourceCombo: this.config.hideSourceCombo || false
           ,listeners: {
              'select': {fn: function(data) {
                this.setValue(data.relativeUrl);
                this.fireEvent('select',data);
              },scope:this}
            }
          });
          this.browser.show(btn);
          return true;
        }
        ,onDestroy: function(){
          MODx.combo.Browser.superclass.onDestroy.call(this);
        }
      });
      Ext.reg('modx-combo-browser',MODx.combo.Browser);
      Скриншот элемента:
      Вставляем поле в CMS MODX для добавления изображения к ресурсу, используя Ext JS
    4. Александр
      Александр
      27.11.2020, 22:44
      Александр, здравствуйте! Огромное спасибо, вывести поле (Изображение) получилось, но как понимаю для работы с ним есть некоторые нюансы?

      Всё сделал по аналогии других полей, добавил поле в таблицу, изменил схему, обновил компонент, внёс изменения в плагин в итоге при добавлении изображения, в таблицу добавляется значение, (url изображения), но при перезагрузки страницы в редактировании ресурса поле «image» становится пустым, возможно где-то я опять начудил, правда проверил всё уже двадцать раз. Как я понимаю у меня не получается получить значение таким образом:
      $image = $extendResource->get('image');
      Возможно для этого поля как-то по-другому это нужно делать?

      Александр и если возможно, подскажите пожалуйста, как нужно сделать чтобы изображение добавленное к ресурсу в редактировании ресурса, отображалось рядом с полем «image»?
    5. Александр Мальцев
      Александр Мальцев
      28.11.2020, 10:46
      Добрый день!
      Тут вроде как обычно:
      1. Добавляем в базу данных поле, например, image:
      Добавление поля image в таблицу базы данных
      2. В «extendresource.mysql.schema.xml» помещаем строчку:
      <field key="image" dbtype="varchar" precision="255" phptype="string" null="false"/>
      3. Обновляем модель.
      4. Вносим изменения в плагин ExtendedResource:
      // ...
      $image = '';
      // ...
      $image = $extendResource->get('image');
      // ...
      page.insert(0,{
        xtype: 'modx-combo-browser'
        ,fieldLabel: 'Изображение'
        ,name: 'image'
        ,id: 'image'
        ,value: '{$image}'
        ,anchor: '100%'
        ,layout: 'anchor'
      });
      // ...
      $extendResource->set('image', $_POST['image']);
      // ...
    6. Александр Мальцев
      Александр Мальцев
      28.11.2020, 10:52
      Для того чтобы дополнительно вывести рядом с полем image картинку необходимо внести следующие изменения в код:
      // ...
      page.insert(1,{
        xtype: 'panel'
        ,id: 'image-panel'
        ,border: false
        ,bodyStyle: 'margin-top: 10px;'
        ,html: '<img id="image-resource" src="/{$image}" style="max-width: 100%; height: auto;">'
      });
      // ...
      ,listeners: {
        'select': {fn: function(data) {
          this.setValue(data.relativeUrl);
          // добавить ещё следующее
          var imageResource = Ext.get('image-resource');
          imageResource.set({
            src: '/'+data.relativeUrl
          });
      // ...
    7. Александр
      Александр
      28.11.2020, 13:07
      Александр, здравствуйте! Получается я не указал в параметрах поля:
      ,value: '{$image}'
      по этому были проблемы. Огромное Вам спасибо!
    8. Александр
      Александр
      28.11.2020, 13:14
      Я изначально додумался только до того, чтобы использовать поле для вывода изображения, но тогда при редактировании ресурса и выборе изображения не будет обновления изображения на лету, а этот вариант просто идеальный, большое спасибо!
  7. Александр
    Александр
    12.11.2020, 15:44
    Александр, здравствуйте! Пытаюсь вывести поля в компоненте Comparison (Сравнение товаров), делаю таким образом:
    [[!CompareList?
      &loadModels=`extendresource`
      &leftJoin=`{
        "extendresource": {
          "class": "extendResource",
          "alias": "extFields",
          "on": "extFields.resource = modResource.id"
        }
      }`
      &select=`{"extFields": "extFields.country as country,extFields.date as date,extFields.size as size,extFields.context as context"}`  
    }`
    ]]
    Но не получается это сделать, подскажите пожалуйста, как можно использовать свои поля в компоненте Comparison?
    1. Александр Мальцев
      Александр Мальцев
      12.11.2020, 16:07
      Александр, CompareList не использовал. Может он это просто не умеет. Если это так, то тогда только разрабатывать свой сниппет.
    2. Александр
      Александр
      12.11.2020, 17:01
      В мануале этого компонента указано (вы можете подключить значения из таблицы msProductFil) и приведён пример с параметром «leftjoin» и «Select» Подключение значения из таблицы msProductFil в CMS MODXАлександр, если теоретически, можно ли c этого примера сделать вывод, что он будет работать с другими полями?
    3. Александр Мальцев
      Александр Мальцев
      13.11.2020, 14:54
      Александр, у меня нет CompareList. В нём наверно нет «modResource.id». Нужно вместо этого поля указать другое.
    4. Александр
      Александр
      13.11.2020, 17:08
      Александр, чтобы уже точно убедится что использовать «CompareList» для своих полей не получится на всякий случай скину ссылку на сниппет CompareList, если у Вас будет время, посмотрите пожалуйста.
    5. Александр Мальцев
      Александр Мальцев
      14.11.2020, 04:54
      Если он у вас используется для сравнения товаров, то «msProduct.id», иначе «modResource.id». Если не получится, то в документации CompareList имеется пример с использованием prepareSnippet. Можете сделать через него.
    6. Александр
      Александр
      14.11.2020, 09:45
      Спасибо!
  8. Александр
    Александр
    05.11.2020, 19:13
    Александр, здравствуйте! Всё реализовал по данному руководству, всё получилось, ещё раз спасибо за данное решение, но есть проблема, плагин почему-то добавляет значения в таблицу базы, разделяя их запятой, пример: «дайвинг, плаванье, лыжи» менял в плагине вот эту строку:

    $extendResource->set('myhobbies', implode('||', $_POST['myhobbies']));
    указав там разделитель || тогда в таблице сохраняет как нужно, но при таком раскладе в админке при перезагрузке страницы, выбранные значения слетают.

    1. Скажите пожалуйста что нужно поправить, чтобы разделитель у значений в базе данных был "||"?

    2. Как можно сделать чтобы выводить определённые поля в дополнительной вкладке админки?

    3. Можно ли указать какое поле и в каком шаблоне использовать?

    4. Если можно, к примеру добавить иконки, картинку, стили к значениям в админке, то как лучше это сделать?

    Если возможно, подскажите пожалуйста.
    1. Александр Мальцев
      Александр Мальцев
      06.11.2020, 15:59
      Привет!
      1. В этом случае нужно при получении значения заменить || на запятую. Т.е.:
      // эту строчку 
      $myhobbies = $extendResource->get('myhobbies');
      // заменить на
      $myhobbies = str_replace('||',',',$extendResource->get('myhobbies'));
      2. Можно, но готового кода нет, т.к. такой необходимости не было.
      3. Можно, для этого следует получить шаблон ресурса, а далее в зависимости от него реализовать определённую логику:
      // получим id шаблона ресурса
      $template = $resource->get('template');
      4. Добавить стили в админку, например, можно так:
      $modx->controller->addCss($modx->getOption('assets_url') . 'bootstrap/css/bootstrap.min.css');
      Кроме этого можно сделать и многие другие вещи, тут нужно просто разобраться как с ней работать.
    2. Александр
      Александр
      06.11.2020, 18:20
      Александр, большое спасибо за примеры! Правда касаемо первого вопроса, возможно я не точно описал суть проблемы, в нём речь идёт не о получении значений при помощи плагина ExtendResource, а о сохранении их в базу данных с разделителем || плагин ExtendedResource, проблема в следующем, при выборе значений поля myhobbies в админке при редактировании ресурса, в phpmyadmin в таблице в ячейке значения сохраняются через запятую, вот таким образом: «дайвинг, плаванье, лыжи» а нужно чтобы разделитель был || как я понимаю с каким разделителем выбранные значения поля myhobbies будут хранится в таблице в phpmyadmin, отвечает строка плагина ExtendedResource:
      $extendResource->set('myhobbies', implode(',', $_POST['myhobbies']));
      точнее параметр implode, если в нём убрать запятую и поставить || тогда значения в таблице сохраняются правильно «дайвинг||плаванье||лыжи» но тогда возникает проблема, выбрав значения при редактировании ресурса, нажимаешь сохранить, перезагружаешь страницу а поле пустое, но в phpmyadmin в таблице они есть, подскажите пожалуйста что нужно поправить?

      Phpmyadmin, ячейка таблицы как хранятся выбранные значения
      Как сохраняются выбранные значения в базе данных
    3. Александр Мальцев
      Александр Мальцев
      07.11.2020, 02:51
      Так правильно, при сохранении вы используете разделитель ||:
      $extendResource->set('myhobbies', implode('||', $_POST['myhobbies']));
      А при получении преобразовываете его в запятую:
      $myhobbies = str_replace('||',',',$extendResource->get('myhobbies'));
    4. Александр
      Александр
      07.11.2020, 03:20
      Да, но проблема в том что если я в параметре implode использую разделитель || в место запятой, то в админке в поле выбранные значения у ресурса:
      Выбранные значения в поле у ресурса в CMS MODXпри перезагрузки страницы слетают, просто пустое поле становится:
      Выбранные значения в поле у ресурса после перезагрузки в CMS MODXможет это зависит от параметров таблицы? Что можно попробовать сделать в данном случае?
    5. Александр Мальцев
      Александр Мальцев
      07.11.2020, 11:27
      В базу сохраняем с использованием разделителя ||:
      $extendResource->set('myhobbies', implode('||', $_POST['myhobbies']));
      При получении значения из базы заменяем || на запятую:
      $myhobbies = str_replace('||',',',$extendResource->get('myhobbies'));
      А что в этом случае конкретно не работает? Запятая как была, так и осталась, только в базе значение хранится с помощью разделителя ||.
    6. Александр
      Александр
      07.11.2020, 15:33
      Александр, если я делаю так:
      $extendResource->set('myhobbies', implode('||', $_POST['myhobbies']));
      как вы и говорите в базе сохраняется с разделителем || но начинаются проблемы в админке при выборе значений поля, к примеру редактирую ресурс, выбираю в поле myhobbies (Мои увлечения) Бег, Дайвинг, Лыжи, нажимаю сохранить, перезагружаю страницу а поле (Мои увлечения) пустое как будто-то, не чего не выбрано.

      Если делаю так:
      $extendResource->set('myhobbies', implode(',', $_POST['myhobbies']));
      В админке при добавлении значений к ресурсу, проблем нет, но тогда в в базе значения сохраняются через запятую.

      С чем это может быть связано, что можно ещё попробовать сделать в данном случае?
    7. Александр Мальцев
      Александр Мальцев
      07.11.2020, 15:50
      Так написал, что нужно изменить ещё в одном месте (при получении данных):
      ...
      $size = '';
      $myhobbies = '';
      ...
      $size = $extendResource->get('size');
      //$myhobbies = $extendResource->get('myhobbies');
      $myhobbies = str_replace('||',',',$extendResource->get('myhobbies'));
    8. Александр
      Александр
      07.11.2020, 16:34
      Честно говоря, как-то даже не ловко, что я не сразу понял с предыдущих ваших ответов всю суть для решения проблемы, огромное спасибо! А за что отвечает этот параметр:
      page.insert(6,
      Александр и если возможно, есть две проблемы, с которыми тоже не получается разобраться:

      1. Не сохраняет в базу значения, если используешь это поле для категории ресурсов, почему так?

      2. И не получается вывести в результатах mFilter2, [[!+extend.myhobbies]], как это можно попробовать решить?
    9. Александр
      Александр
      07.11.2020, 17:34
      Александр по поводу первого моего вопроса (1. Не сохраняет в базу значения, если используешь это поле для категории ресурсов, почему так?), получилось решить проблему, указав у всех полей, кроме поля (id) и (resources) По умолчанию NULL, но на сколько это правильно и стоит ли так делать?
    10. Александр Мальцев
      Александр Мальцев
      12.11.2020, 14:35
      Этот пример вставляет на страницу блок после 6 элемента в указанной секции.
      1. Не знаю с чем у вас это связано. Если ресурс является контейнером всё сохраняется.
      2. Необходимо в сниппет mFilter2 добавить модель extendResource (&loadModels), соединение с таблицей content_extend (&leftjoin) и выбрать нужные поля из таблицы (&select).
    11. Александр Мальцев
      Александр Мальцев
      12.11.2020, 14:40
      Александр, нужно проверить индексы таблицы в базе данных.
    12. Александр
      Александр
      12.11.2020, 14:53
      Александр, спасибо! Первая проблема была из-за не правильной структуры таблицы сейчас всё работает, вторая тоже по моей невнимательности, ещё раз спасибо за помощь.
    13. Александр
      Александр
      12.11.2020, 15:11
      Спасибо!
  9. Александр
    Александр
    09.10.2019, 21:40
    Отличное руководство, спасибо! Скажите пожалуйста, как можно сделать, чтобы в админке к примеру поле level было выпадающим списком, множественный выбор или чекбоксами, аналогично тв?
    1. Александр Мальцев
      Александр Мальцев
      12.10.2019, 13:06
      Спасибо за добрые слова. Информацию по checkbox полю добавил в статью.
    2. Александр
      Александр
      12.10.2019, 16:24
      Огромное спасибо за очень нужную и полезную информацию.
    3. Александр Мальцев
      Александр Мальцев
      13.10.2019, 07:29
      Информацию по остальным двум моментам тоже добавил в статью.
    4. Александр
      Александр
      16.10.2019, 09:01
      Александр, спасибо. Очень нужная и максимально понятная информация.
  10. Aleksandr Dom
    Aleksandr Dom
    22.07.2019, 08:54
    Добрый день.
    Не подскажите, как с помощью формы на странице, добавить запись в свою таблицу БД?
    Т.е. таблицу сделал. Схему написал. С выводом вроде бы всё понятно. А вот как формой (php или formit) не соображу.
  11. Сеокотов
    Сеокотов
    12.07.2018, 16:57
    есть ли какие то преимущества в скорости работы с этими полями перед TVшками? Или это только для удобства администрирования?
    1. Александр Мальцев
      Александр Мальцев
      12.07.2018, 17:35
      Конечно, есть. Если, например, в проекте используется 7 TV. То для получения их значений для данного ресурса необходимо будет использовать 7 конструкций &leftJoin. И соответственно данный запрос будет выполняться намного дольше, чем, если бы получить все эти значения из одной строки таблицы. В последнем случае понадобится всего один &leftJoin.
      Кроме этого используя эту инструкцию, можно установить полям необходимый тип данных, в случае с TV это сделать нельзя, их значение всегда имеет тип mediumtext. А это создаёт трудности для фильтрации и сортировки.
  12. Сергей
    Сергей
    03.09.2017, 19:37
    Сделал компонент Extend с таблицей Extendresource в БД и с 4 дополнительными полями:
    depth, width, length, grid.
    Но по аналогии с вашим кодом у меня не заработало, но в результате разбирательств у меня корректно заработал такой код:
    <?php
    $modx->addPackage('Extend', $modx->getOption('core_path') . 'components/Extend/model/', 'modx_');
    
    switch ($modx->event->name) {
      case 'OnDocFormRender':
        $Extendresource = $modx->getObject('Extendresource', array('id_resource' => $id));
        if ($mode == 'upd' && $Extendresource) {
          $depth = $Extendresource->get('depth');
          $width = $Extendresource->get('width');
          $length = $Extendresource->get('length');
          $grid = $Extendresource->get('grid');
        }
        $modx->controller->addHtml(<<<HTML
    <script>
      Ext.ComponentMgr.onAvailable('modx-resource-main-right', function(page) {
        page.on('beforerender', function() {
          page.insert(2,{
            xtype: 'textfield'
            ,name: 'depth'
            ,value: '{$depth}'
            ,anchor: '100%'
            ,layout: 'anchor'
            ,fieldLabel: 'Глубина'
          });
          page.insert(3,{
            xtype: 'textfield'
            ,name: 'width'
            ,value: '{$width}'
            ,anchor: '100%'
            ,layout: 'anchor'
            ,fieldLabel: 'Ширина'
          });
          page.insert(4,{
            xtype: 'textfield'
            ,name: 'length'
            ,value: '{$length}'
            ,anchor: '100%'
            ,layout: 'anchor'
            ,fieldLabel: 'Длина'
          });     
        })
      });
      Ext.ComponentMgr.onAvailable('modx-resource-main-left', function(page) {
        page.on('beforerender', function() {
          page.insert(2,{
            xtype: 'textfield'
            ,name: 'grid'
            ,value: '{$grid}'
            ,anchor: '100%'
            ,layout: 'anchor'
            ,fieldLabel: 'Декоративная решетка'
          });
        })
      });
    </script>
    HTML
    );
        break;
      case 'OnDocFormSave':
        $depth = $resource->get('depth');
        $width = $resource->get('width');
        $length = $resource->get('length');
        $grid = $resource->get('grid');
        if (!$Extendresource = $modx->getObject('Extendresource', array('id_resource' => $id))) {
          $Extendresource = $modx->newObject('Extendresource', array(
            'depth' => $depth,
            'width' => $width,
            'length' => $length,
            'grid' => $grid
          ));
        }
        $Extendresource->set('depth', $depth);
        $Extendresource->set('width', $width);
        $Extendresource->set('length', $length);
        $Extendresource->set('grid', $grid);
        $Extendresource->save();
        break;
    }
    return;
  13. Сергей
    Сергей
    03.09.2017, 13:00
    Сделал, все как написано.
    В админке дополнительные поля не отображаются. В журнале ошибок пусто.
    Похоже вот это не работает, хотя плагин отрабатывает.
    $modx->controller->addHtml(<<<HTML
    <script>
      Ext.ComponentMgr.onAvailable('modx-resource-main-right', function(page) {
        page.on('beforerender', function() {
          page.insert(2,{
            xtype: 'textfield'
            ,name: 'views'
            ,value: {$views}
            ,anchor: '100%'
            ,layout: 'anchor'
            ,fieldLabel: 'Просмотры'
          });
          page.insert(3,{
            xtype: 'textfield'
            ,name: 'level'
            ,value: {$level}
            ,anchor: '100%'
            ,layout: 'anchor'
            ,fieldLabel: 'Уровень'
          });
        })
      });
      Ext.ComponentMgr.onAvailable('modx-resource-main-left', function(page) {
        page.on('beforerender', function() {
          page.insert(2,{
            xtype: 'textfield'
            ,name: 'keywords'
            ,value: '{$keywords}'
            ,anchor: '100%'
            ,layout: 'anchor'
            ,fieldLabel: 'Ключевые слова'
          });
        })
      });
    </script>
    HTML
    );
    1. Сергей
      Сергей
      03.09.2017, 14:52
      Хм, так поля появились. Значит я где-то накосячил. Буду разбираться.
  14. Сергей
    Сергей
    31.08.2017, 08:39
    А какого типа надо добавить дополнительное поле к ресурсу (например «Ширина») и при редактировании ресурса добавить несколько вариантов значений в это поле, что бы потом на фронтенде можно было с этого поля сделать DropDown List с теми вариантами которые ми определили в админке?
    Спасибо.
    1. Александр Мальцев
      Александр Мальцев
      31.08.2017, 15:49
      Добавить текстовое поле width в таблицу, например, с типом varchar(255). Обновить XML схему и сгенерировать модель.

      Для разделения значений поля width использовать 2 вертикальные линии.
      Например:
      200||300||900
      После этого создать сниппет outputList, чанки tplOuterList и tplInnerList.

      Сниппет outputList:
      <?php
      $value = $modx->getOption('value', $scriptProperties);
      $tplInnerList = $modx->getOption('tplInnerList', $scriptProperties,'tplInnerList');
      $tplOuterList = $modx->getOption('tplOuterList', $scriptProperties,'tplOuterList');
      
      $array = explode ('||', $value);
      $items = array();
      foreach ($array as $val) {
        $items[] = $modx->getChunk($tplInnerList, array(
          'item' => $val
        ));
      }
      
      $list = implode('', $items);
      
      $output = $modx->getChunk($tplOuterList, array(
        'items' => $list
      ));
      
      return $output;
      
      Чанк tplOuterList:
      <select>[[+items]]</select>
      Чанк tplInnerList:
      <option>[[+item]]</option>
      Использование сниппета outputList в шаблоне или чанке:
      [[!outputList? &value=`[[!getExtendResource? &field=`width`]]`]]
      [[!outputList? &value=`[[+extend.width`]]
  15. Виталий
    Виталий
    16.08.2017, 13:05
    Поясните пожалуйста:
    Поле views (количество просмотров) — будет подсчитывать количество просмотров или надо ещё спец.компоненты устанавливать?
    Поле level (минимальный уровень доступа к ресурсу) — для чего используется?
    1. Александр Мальцев
      Александр Мальцев
      17.08.2017, 13:57
      Это просто пример как можно организовать добавление дополнительный полей к ресурсу. Поля views, level, keywors приведены для примера. Если нужно, например, вести учёт просмотр ресурсов, то эту логику, конечно, необходимо написать дополнительно.

      Эту инструкцию можно использовать в качестве примера. Например, если вы будете создавать сайт по сдачи квартир, то вам понадобится добавить к ресурсу следующие поля: адрес квартиры, площадь, этаж, цена, состояние, и т.д. Если вы будете это делать с помощью TV, то это приведёт не только к большему количеству запросов при выборе нужных данных, но и к сложностям их фильтрации.
    2. Виталий
      Виталий
      17.08.2017, 16:41
      Спасибо.