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