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

Александр Мальцев
Александр Мальцев
18K
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. Павел Андросов
    Павел Андросов
    2021-02-01 17:44:02
    Александр, здравствуйте. В админку все вывелось, но вот в таблицу данные не сохраняются. При перезагрузке — скидывается до данных по умолчанию. Скорее всего — я не добавил код для сохранения данных. Не могли бы вы поподробнее рассказать как сделать сохранение данных. Спасибо
  1. Александр Мальцев
    Александр Мальцев
    2021-02-02 16:07:19
    Здравствуйте! Может забыли включить системное событие OnDocFormSave для плагина?
  • Павел Андросов
    Павел Андросов
    2021-02-02 16:26:54
    Проблема была в создании классов из схемы. Видимо, указал неправильную схему в parse_schema.php. Теперь все работает, огромное спасибо за уроки :)
  • Александр
    Александр
    2020-11-30 21:54:36
    Александр, доброго вечера Вам! Случайно обнаружил «опечаток» в руководстве а точнее в разделе где рассказывается за плагин: «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. Александр Мальцев
      Александр Мальцев
      2020-12-01 14:49:44
      Привет, Александр! Спасибо, так получилось при форматировании кода статьи. Изменил этот момент, а также дополнительно вынес определение этой строки и присвоил её переменной $html. Так мне кажется лучше.
      Это просто такой синтаксис в php для определения строк. Он называется heredoc.
    2. Александр
      Александр
      2020-12-02 02:11:35
      Здравствуйте! Внёс изменения в плагин, спасибо.
  • Александр
    Александр
    2020-11-28 21:05:38
    Александр, здравствуйте! Пытаюсь добавить условие для ограничения вывода своих полей, чтобы вывод полей был только в тех ресурсах у которых id шаблона равен 3 и 4, отчасти получается, но как обычно есть проблемы которые не получается решить, делаю так:
    if(!in_array($resource->get('template'),[3,4])){break;}
    почему-то это условие работает только для ресурсов, которые уже созданы а если добавляешь новый ресурс, то поля выводятся не смотря на то, какой шаблон у ресурса находится в поле (Шаблон), расскажите пожалуйста, как нужно сделать, чтобы при добавлении нового ресурса, поля выводились только в том случае, если в поле (Шаблон) выбран шаблон с id которые указаны в условие?
    1. Александр Мальцев
      Александр Мальцев
      2020-11-29 16:51:22
      Добрый вечер! Эту возможность добавил в код плагина, приведённый в статье. По умолчанию этот код закомментирован. Раскомментируйте и внесите id нужных шаблонов в $templateIds.
    2. Александр
      Александр
      2020-11-29 18:52:01
      Здравствуйте! Александр, огромнейшее спасибо за решение, очень нужный функционал.
  • Александр
    Александр
    2020-11-27 23:30:44
    Александр, доброго вечера Вам! Попал на глаза опечаток в руководстве, где рассказано за плагин «ExtendedResource» в место пакета: «extendresource» указан класс:
    modx->addPackage('extendResource'
    на локалке так работает, без проблем, видимо не так чувствителен к регистру а на хосте уже не хочет.
    1. Александр Мальцев
      Александр Мальцев
      2020-11-29 14:34:02
      Спасибо, Александр! Поправил. Не работало, т.к. название пакета не соответствовало имени папки «extendresource». В Windows имена каталогов и файлов просто не чувствительны к регистру, а в остальных системах это конечно уже будут разные элементы.
  • Amsterdam
    Amsterdam
    2020-11-15 14:44:51
    Александр, добрый день!

    А как можно в minishop2, из карточки товара на фротне, записать определенную информацию в новое отдельное поле и потом вывести ее в админке? Этим способом почему то у меня не получается у товаров вывести доп.поля. Может где то ошибся, или там нужно по другому что то делать?..
    1. Александр Мальцев
      Александр Мальцев
      2020-11-18 14:01:35
      Привет! Нужно проверить, где-то что-то забыли сделать. В админке проблем не должно быть. С фронта наверно не получится, т.к. ms2form работает дополнительно только с TV. Тут скорее всего только своё писать.
  • Александр
    Александр
    2020-11-14 04:23:29
    Александр, здравствуйте! Как можно в админке вывести поле «изображение», подскажите пожалуйста?
    1. Александр Мальцев
      Александр Мальцев
      2020-11-18 15:31:38
      Привет!
      Можно так:
      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. Александр
      Александр
      2020-11-18 21:39:11
      Здравствуйте! Спасибо. Александр, скажите пожалуйста а как можно добавить своё поле, для добавления изображения к ресурсу?
    3. Александр Мальцев
      Александр Мальцев
      2020-11-27 15:04:19
      Привет! Вставить поле для добавления изображения к ресурсу, используя 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. Александр
      Александр
      2020-11-27 22:44:19
      Александр, здравствуйте! Огромное спасибо, вывести поле (Изображение) получилось, но как понимаю для работы с ним есть некоторые нюансы?

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

      Александр и если возможно, подскажите пожалуйста, как нужно сделать чтобы изображение добавленное к ресурсу в редактировании ресурса, отображалось рядом с полем «image»?
    5. Александр Мальцев
      Александр Мальцев
      2020-11-28 10:46:51
      Добрый день!
      Тут вроде как обычно:
      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. Александр Мальцев
      Александр Мальцев
      2020-11-28 10:52:11
      Для того чтобы дополнительно вывести рядом с полем 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. Александр
      Александр
      2020-11-28 13:07:47
      Александр, здравствуйте! Получается я не указал в параметрах поля:
      ,value: '{$image}'
      по этому были проблемы. Огромное Вам спасибо!
    8. Александр
      Александр
      2020-11-28 13:14:38
      Я изначально додумался только до того, чтобы использовать поле для вывода изображения, но тогда при редактировании ресурса и выборе изображения не будет обновления изображения на лету, а этот вариант просто идеальный, большое спасибо!
  • Александр
    Александр
    2020-11-12 15:44: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. Александр Мальцев
      Александр Мальцев
      2020-11-12 16:07:58
      Александр, CompareList не использовал. Может он это просто не умеет. Если это так, то тогда только разрабатывать свой сниппет.
    2. Александр
      Александр
      2020-11-12 17:01:08
      В мануале этого компонента указано (вы можете подключить значения из таблицы msProductFil) и приведён пример с параметром «leftjoin» и «Select» Подключение значения из таблицы msProductFil в CMS MODXАлександр, если теоретически, можно ли c этого примера сделать вывод, что он будет работать с другими полями?
    3. Александр Мальцев
      Александр Мальцев
      2020-11-13 14:54:29
      Александр, у меня нет CompareList. В нём наверно нет «modResource.id». Нужно вместо этого поля указать другое.
    4. Александр
      Александр
      2020-11-13 17:08:19
      Александр, чтобы уже точно убедится что использовать «CompareList» для своих полей не получится на всякий случай скину ссылку на сниппет CompareList, если у Вас будет время, посмотрите пожалуйста.
    5. Александр Мальцев
      Александр Мальцев
      2020-11-14 04:54:06
      Если он у вас используется для сравнения товаров, то «msProduct.id», иначе «modResource.id». Если не получится, то в документации CompareList имеется пример с использованием prepareSnippet. Можете сделать через него.
    6. Александр
      Александр
      2020-11-14 09:45:27
      Спасибо!
  • Александр
    Александр
    2020-11-05 19:13:21
    Александр, здравствуйте! Всё реализовал по данному руководству, всё получилось, ещё раз спасибо за данное решение, но есть проблема, плагин почему-то добавляет значения в таблицу базы, разделяя их запятой, пример: «дайвинг, плаванье, лыжи» менял в плагине вот эту строку:

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

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

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

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

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

    Если возможно, подскажите пожалуйста.
    1. Александр Мальцев
      Александр Мальцев
      2020-11-06 15:59:13
      Привет!
      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. Александр
      Александр
      2020-11-06 18:20:18
      Александр, большое спасибо за примеры! Правда касаемо первого вопроса, возможно я не точно описал суть проблемы, в нём речь идёт не о получении значений при помощи плагина ExtendResource, а о сохранении их в базу данных с разделителем || плагин ExtendedResource, проблема в следующем, при выборе значений поля myhobbies в админке при редактировании ресурса, в phpmyadmin в таблице в ячейке значения сохраняются через запятую, вот таким образом: «дайвинг, плаванье, лыжи» а нужно чтобы разделитель был || как я понимаю с каким разделителем выбранные значения поля myhobbies будут хранится в таблице в phpmyadmin, отвечает строка плагина ExtendedResource:
      $extendResource->set('myhobbies', implode(',', $_POST['myhobbies']));
      точнее параметр implode, если в нём убрать запятую и поставить || тогда значения в таблице сохраняются правильно «дайвинг||плаванье||лыжи» но тогда возникает проблема, выбрав значения при редактировании ресурса, нажимаешь сохранить, перезагружаешь страницу а поле пустое, но в phpmyadmin в таблице они есть, подскажите пожалуйста что нужно поправить?

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

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

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

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

      2. И не получается вывести в результатах mFilter2, [[!+extend.myhobbies]], как это можно попробовать решить?
    9. Александр
      Александр
      2020-11-07 17:34:01
      Александр по поводу первого моего вопроса (1. Не сохраняет в базу значения, если используешь это поле для категории ресурсов, почему так?), получилось решить проблему, указав у всех полей, кроме поля (id) и (resources) По умолчанию NULL, но на сколько это правильно и стоит ли так делать?
    10. Александр Мальцев
      Александр Мальцев
      2020-11-12 14:35:56
      Этот пример вставляет на страницу блок после 6 элемента в указанной секции.
      1. Не знаю с чем у вас это связано. Если ресурс является контейнером всё сохраняется.
      2. Необходимо в сниппет mFilter2 добавить модель extendResource (&loadModels), соединение с таблицей content_extend (&leftjoin) и выбрать нужные поля из таблицы (&select).
    11. Александр Мальцев
      Александр Мальцев
      2020-11-12 14:40:47
      Александр, нужно проверить индексы таблицы в базе данных.
    12. Александр
      Александр
      2020-11-12 14:53:10
      Александр, спасибо! Первая проблема была из-за не правильной структуры таблицы сейчас всё работает, вторая тоже по моей невнимательности, ещё раз спасибо за помощь.
    13. Александр
      Александр
      2020-11-12 15:11:05
      Спасибо!
  • Александр
    Александр
    2019-10-09 21:40:59
    Отличное руководство, спасибо! Скажите пожалуйста, как можно сделать, чтобы в админке к примеру поле level было выпадающим списком, множественный выбор или чекбоксами, аналогично тв?
    1. Александр Мальцев
      Александр Мальцев
      2019-10-12 13:06:02
      Спасибо за добрые слова. Информацию по checkbox полю добавил в статью.
    2. Александр
      Александр
      2019-10-12 16:24:08
      Огромное спасибо за очень нужную и полезную информацию.
    3. Александр Мальцев
      Александр Мальцев
      2019-10-13 07:29:04
      Информацию по остальным двум моментам тоже добавил в статью.
    4. Александр
      Александр
      2019-10-16 09:01:52
      Александр, спасибо. Очень нужная и максимально понятная информация.
  • Aleksandr Dom
    Aleksandr Dom
    2019-07-22 08:54:52
    Добрый день.
    Не подскажите, как с помощью формы на странице, добавить запись в свою таблицу БД?
    Т.е. таблицу сделал. Схему написал. С выводом вроде бы всё понятно. А вот как формой (php или formit) не соображу.
    1. Сеокотов
      Сеокотов
      2018-07-12 16:57:02
      есть ли какие то преимущества в скорости работы с этими полями перед TVшками? Или это только для удобства администрирования?
      1. Александр Мальцев
        Александр Мальцев
        2018-07-12 17:35:30
        Конечно, есть. Если, например, в проекте используется 7 TV. То для получения их значений для данного ресурса необходимо будет использовать 7 конструкций &leftJoin. И соответственно данный запрос будет выполняться намного дольше, чем, если бы получить все эти значения из одной строки таблицы. В последнем случае понадобится всего один &leftJoin.
        Кроме этого используя эту инструкцию, можно установить полям необходимый тип данных, в случае с TV это сделать нельзя, их значение всегда имеет тип mediumtext. А это создаёт трудности для фильтрации и сортировки.
    2. Сергей
      Сергей
      2017-09-03 19:37:24
      Сделал компонент 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;
      1. Сергей
        Сергей
        2017-09-03 13:00:19
        Сделал, все как написано.
        В админке дополнительные поля не отображаются. В журнале ошибок пусто.
        Похоже вот это не работает, хотя плагин отрабатывает.
        $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. Сергей
          Сергей
          2017-09-03 14:52:29
          Хм, так поля появились. Значит я где-то накосячил. Буду разбираться.
      2. Сергей
        Сергей
        2017-08-31 08:39:25
        А какого типа надо добавить дополнительное поле к ресурсу (например «Ширина») и при редактировании ресурса добавить несколько вариантов значений в это поле, что бы потом на фронтенде можно было с этого поля сделать DropDown List с теми вариантами которые ми определили в админке?
        Спасибо.
        1. Александр Мальцев
          Александр Мальцев
          2017-08-31 15:49:44
          Добавить текстовое поле 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`]]
      3. Виталий
        Виталий
        2017-08-16 13:05:33
        Поясните пожалуйста:
        Поле views (количество просмотров) — будет подсчитывать количество просмотров или надо ещё спец.компоненты устанавливать?
        Поле level (минимальный уровень доступа к ресурсу) — для чего используется?
        1. Александр Мальцев
          Александр Мальцев
          2017-08-17 13:57:18
          Это просто пример как можно организовать добавление дополнительный полей к ресурсу. Поля views, level, keywors приведены для примера. Если нужно, например, вести учёт просмотр ресурсов, то эту логику, конечно, необходимо написать дополнительно.

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