- Добавление таблицы в базу данных
- Создание директории для компонента
- Создание XML схемы компонента
- Генерирование модели компонента
- Принцип работы с компонентом extendresource
- Представление расширенных полей ресурса в админке
- Как добавить checkbox поле к компоненту и отобразить его в админке
- Как в админке MODX создать поля с одиночным и множественным выбором из списка
- Добавление радиокнопок в форму ресурса
- Комментарии
Расширение стандартных полей ресурса через свою таблицу в MODX

Статья, в которой рассмотрим способ добавления дополнительных полей к ресурсу без использования 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.

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
:
- Открыть файл в текстовом редакторе и ввести название компонента.
- Положить его в корень MODX сайта.
- Открыть данный файл из браузера.
После выполнения скрипта в каталоге «core/components/extendresource/model/» будут созданы 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
$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. Поэтому на странице создания плагина во вкладке «Системные события» необходимо установить галочки напротив них.

Событие 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;
}

Как добавить checkbox поле к компоненту и отобразить его в админке
Процесс добавления checkbox поля к компоненту и представление его в админке состоит из следующих шагов:
1. Добавить в таблицу site_content_extend
, например, поле isquestion
. Характеристики: тип - tinyint(1)
, атрибуты – unsigned
, по умолчанию – 0
.

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']);

Как в админке MODX создать поля с одиночным и множественным выбором из списка
В этом примере создадим 2 поля. Первое поле – это size
. Заполнение этого поля в админке организуем из выпадающего списка с возможностью выбора только одного значения. Второе поле – это myhobbies
. Данные этого поля могут состоять из нескольких значений устанавливаемых из списка.
Основные шаги:
1. Добавим в таблицу site_content_extend
2 поля.
- Характеристики поля
size
: тип -varchar(5)
, сравнение –utf8_general_ci
, по умолчанию – пустая строка. - Характеристики поля
myhobbies
: тип -varchar(255)
, сравнение –utf8_general_ci
, по умолчанию – пустая строка.

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']));
...


Добавление радиокнопок в форму ресурса
Например, создадим кастомное поле color
. Заполнение этого поля на форме ресурса организуем посредством радиокнопок.

Для этого:
1. Добавим color
в таблицу site_content_extend
:

2. Вставим в файл extendresource.mysql.schema.xml
эту строчку:
<field key="color" dbtype="varchar" precision="20" phptype="string" null="false" default="" />
3. Обновим модель компонента с помощью выполнения уже настроенного скрипта parse_schema.php
.
4. Доработаем код плагина ExtendedResource
:
...
$color = '';
...
$color = $extendResource->get('color');
...
page.insert(2,{
xtype: 'radiogroup'
,fieldLabel: 'Цвет'
,columns: 1
,items: [{
id: 'color-white'
,name: 'color'
,boxLabel: 'белый'
,xtype: 'radio'
,inputValue: 'white'
,value: 'white'
,checked: '$color' === 'white' || '$color' === '' ? true : false
},{
id: 'color-black'
,name: 'color'
,boxLabel: 'чёрный'
,xtype: 'radio'
,inputValue: 'black'
,value: 'black'
,checked: '$color' === 'black' ? true : false
}]
});
...
$extendResource->set('color', $_POST['color']);
...
Комментарии: 64
Приветствую Александр! Хорошая статья!
Почти все разобрали, но нет еще одного - это radioподскажите пожалуйста ExtJs вызов radio с данными, условно значения 1,2,3
P.S. и кнопку Комментировать советую сделать как то выделяющуюся , пришлось искать в начале) сливается оранжевая с "Ответить"
Привет! Спасибо! Постараюсь это в ближайшее время добавить.
Александр, не нашлось времени?
Добавил информацию в статью.
Спасибо огромное!
Интересно, почему так происходит?
Это просто такой синтаксис в php для определения строк. Он называется heredoc.
А как можно в minishop2, из карточки товара на фротне, записать определенную информацию в новое отдельное поле и потом вывести ее в админке? Этим способом почему то у меня не получается у товаров вывести доп.поля. Может где то ошибся, или там нужно по другому что то делать?..
Можно так:
Скриншот элемента:
Всё сделал по аналогии других полей, добавил поле в таблицу, изменил схему, обновил компонент, внёс изменения в плагин в итоге при добавлении изображения, в таблицу добавляется значение, (url изображения), но при перезагрузки страницы в редактировании ресурса поле «image» становится пустым, возможно где-то я опять начудил, правда проверил всё уже двадцать раз. Как я понимаю у меня не получается получить значение таким образом:
Возможно для этого поля как-то по-другому это нужно делать?
Александр и если возможно, подскажите пожалуйста, как нужно сделать чтобы изображение добавленное к ресурсу в редактировании ресурса, отображалось рядом с полем «image»?
Тут вроде как обычно:
1. Добавляем в базу данных поле, например, image:
2. В «extendresource.mysql.schema.xml» помещаем строчку:
3. Обновляем модель.
4. Вносим изменения в плагин ExtendedResource:
Но не получается это сделать, подскажите пожалуйста, как можно использовать свои поля в компоненте Comparison?
указав там разделитель || тогда в таблице сохраняет как нужно, но при таком раскладе в админке при перезагрузке страницы, выбранные значения слетают.
1. Скажите пожалуйста что нужно поправить, чтобы разделитель у значений в базе данных был "||"?
2. Как можно сделать чтобы выводить определённые поля в дополнительной вкладке админки?
3. Можно ли указать какое поле и в каком шаблоне использовать?
4. Если можно, к примеру добавить иконки, картинку, стили к значениям в админке, то как лучше это сделать?
Если возможно, подскажите пожалуйста.
1. В этом случае нужно при получении значения заменить || на запятую. Т.е.:
2. Можно, но готового кода нет, т.к. такой необходимости не было.
3. Можно, для этого следует получить шаблон ресурса, а далее в зависимости от него реализовать определённую логику:
4. Добавить стили в админку, например, можно так:
Кроме этого можно сделать и многие другие вещи, тут нужно просто разобраться как с ней работать.
Phpmyadmin, ячейка таблицы как хранятся выбранные значения
А при получении преобразовываете его в запятую:
При получении значения из базы заменяем || на запятую:
А что в этом случае конкретно не работает? Запятая как была, так и осталась, только в базе значение хранится с помощью разделителя ||.
как вы и говорите в базе сохраняется с разделителем || но начинаются проблемы в админке при выборе значений поля, к примеру редактирую ресурс, выбираю в поле myhobbies (Мои увлечения) Бег, Дайвинг, Лыжи, нажимаю сохранить, перезагружаю страницу а поле (Мои увлечения) пустое как будто-то, не чего не выбрано.
Если делаю так:
В админке при добавлении значений к ресурсу, проблем нет, но тогда в в базе значения сохраняются через запятую.
С чем это может быть связано, что можно ещё попробовать сделать в данном случае?
1. Не сохраняет в базу значения, если используешь это поле для категории ресурсов, почему так?
2. И не получается вывести в результатах mFilter2, [[!+extend.myhobbies]], как это можно попробовать решить?
1. Не знаю с чем у вас это связано. Если ресурс является контейнером всё сохраняется.
2. Необходимо в сниппет mFilter2 добавить модель extendResource (&loadModels), соединение с таблицей content_extend (&leftjoin) и выбрать нужные поля из таблицы (&select).
Не подскажите, как с помощью формы на странице, добавить запись в свою таблицу БД?
Т.е. таблицу сделал. Схему написал. С выводом вроде бы всё понятно. А вот как формой (php или formit) не соображу.
Кроме этого используя эту инструкцию, можно установить полям необходимый тип данных, в случае с TV это сделать нельзя, их значение всегда имеет тип mediumtext. А это создаёт трудности для фильтрации и сортировки.
depth, width, length, grid.
Но по аналогии с вашим кодом у меня не заработало, но в результате разбирательств у меня корректно заработал такой код:
В админке дополнительные поля не отображаются. В журнале ошибок пусто.
Похоже вот это не работает, хотя плагин отрабатывает.
Спасибо.
Для разделения значений поля width использовать 2 вертикальные линии.
Например:
После этого создать сниппет outputList, чанки tplOuterList и tplInnerList.
Сниппет outputList:
Чанк tplOuterList:
Чанк tplInnerList:
Использование сниппета outputList в шаблоне или чанке:
Поле views (количество просмотров) — будет подсчитывать количество просмотров или надо ещё спец.компоненты устанавливать?
Поле level (минимальный уровень доступа к ресурсу) — для чего используется?
Эту инструкцию можно использовать в качестве примера. Например, если вы будете создавать сайт по сдачи квартир, то вам понадобится добавить к ресурсу следующие поля: адрес квартиры, площадь, этаж, цена, состояние, и т.д. Если вы будете это делать с помощью TV, то это приведёт не только к большему количеству запросов при выборе нужных данных, но и к сложностям их фильтрации.