Статья, в которой рассмотрим способ добавления дополнительных полей к ресурсу без использования 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.
MODX Revolution – Как добавить таблицу в базу данных с помощью инструмента phpmyadmin
MODX Revolution – Как добавить таблицу в базу данных с помощью инструмента 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="pk" />
        <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 – Шаг 1. Ввод название компонента в утилиту parse_schema.php
MODX Revolution – Ввод название компонента в утилиту parse_schema.php
MODX Revolution – Шаг 3. Открытие файла 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/');
$id = $modx->resource->get('id');
$views = 0;
$keywords='';
$level = 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 – Установка событий, которые должен отслеживать этот плагин
MODX Revolution – Установка событий, которые должен отслеживать этот плагин

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

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

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

<?php

$modx->addPackage('extendResource', $modx->getOption('core_path').'components/extendresource/model/');
 
switch ($modx->event->name) {
    case 'OnDocFormPrerender':
        $views = 0;
        $keywords='';
        $level = 0;
        if (isset($scriptProperties['resource'])) {
            $id = $scriptProperties['resource']->get('id');
            $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(<<<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
);
        break;
        
    case 'OnDocFormSave':
        // do processing logic here. 
        $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;
}
return;

MODX Revolution – Отображение расширенных полей на страницах создания и редактирования ресурсов
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 списка с множественным выбором