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

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

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

PHP
$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.

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

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

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

PHP
<?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):

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

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

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

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

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

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

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

PHP
<?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 схему компонента, т.е. добавить в неё описание этого поля:

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

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

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

PHP
<?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:

XML
<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:

PHP
...
$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 списка с множественным выбором

Добавление радиокнопок в форму ресурса

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

Добавления дополнительного поля color в форму ресурса MODX

Для этого:

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

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

2. Вставим в файл extendresource.mysql.schema.xml эту строчку:

XML
<field key="color" dbtype="varchar" precision="20" phptype="string" null="false" default="" />

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

4. Доработаем код плагина ExtendedResource:

PHP
...
$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

kossin17
kossin17

Приветствую Александр! Хорошая статья!

Почти все разобрали, но нет еще одного - это radio

подскажите пожалуйста ExtJs вызов radio с данными, условно значения 1,2,3

P.S. и кнопку Комментировать советую сделать как то выделяющуюся , пришлось искать в начале) сливается оранжевая с "Ответить"

Александр Мальцев
Александр Мальцев

Привет! Спасибо! Постараюсь это в ближайшее время добавить.

kossin17
kossin17

Александр, не нашлось времени?

Александр Мальцев
Александр Мальцев

Добавил информацию в статью.

kossin17
kossin17

Спасибо огромное!

Павел Андросов
Павел Андросов
Александр, здравствуйте. В админку все вывелось, но вот в таблицу данные не сохраняются. При перезагрузке — скидывается до данных по умолчанию. Скорее всего — я не добавил код для сохранения данных. Не могли бы вы поподробнее рассказать как сделать сохранение данных. Спасибо
Александр Мальцев
Александр Мальцев
Здравствуйте! Может забыли включить системное событие OnDocFormSave для плагина?
Павел Андросов
Павел Андросов
Проблема была в создании классов из схемы. Видимо, указал неправильную схему в parse_schema.php. Теперь все работает, огромное спасибо за уроки :)
Александр
Александр
Александр, доброго вечера Вам! Случайно обнаружил «опечаток» в руководстве а точнее в разделе где рассказывается за плагин: «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
);
Интересно, почему так происходит?
Александр Мальцев
Александр Мальцев
Привет, Александр! Спасибо, так получилось при форматировании кода статьи. Изменил этот момент, а также дополнительно вынес определение этой строки и присвоил её переменной $html. Так мне кажется лучше.
Это просто такой синтаксис в php для определения строк. Он называется heredoc.
Александр
Александр
Здравствуйте! Внёс изменения в плагин, спасибо.
Александр
Александр
Александр, здравствуйте! Пытаюсь добавить условие для ограничения вывода своих полей, чтобы вывод полей был только в тех ресурсах у которых id шаблона равен 3 и 4, отчасти получается, но как обычно есть проблемы которые не получается решить, делаю так:
if(!in_array($resource->get('template'),[3,4])){break;}
почему-то это условие работает только для ресурсов, которые уже созданы а если добавляешь новый ресурс, то поля выводятся не смотря на то, какой шаблон у ресурса находится в поле (Шаблон), расскажите пожалуйста, как нужно сделать, чтобы при добавлении нового ресурса, поля выводились только в том случае, если в поле (Шаблон) выбран шаблон с id которые указаны в условие?
Александр Мальцев
Александр Мальцев
Добрый вечер! Эту возможность добавил в код плагина, приведённый в статье. По умолчанию этот код закомментирован. Раскомментируйте и внесите id нужных шаблонов в $templateIds.
Александр
Александр
Здравствуйте! Александр, огромнейшее спасибо за решение, очень нужный функционал.
Александр
Александр
Александр, доброго вечера Вам! Попал на глаза опечаток в руководстве, где рассказано за плагин «ExtendedResource» в место пакета: «extendresource» указан класс:
modx->addPackage('extendResource'
на локалке так работает, без проблем, видимо не так чувствителен к регистру а на хосте уже не хочет.
Александр Мальцев
Александр Мальцев
Спасибо, Александр! Поправил. Не работало, т.к. название пакета не соответствовало имени папки «extendresource». В Windows имена каталогов и файлов просто не чувствительны к регистру, а в остальных системах это конечно уже будут разные элементы.
Amsterdam
Amsterdam
Александр, добрый день!

А как можно в minishop2, из карточки товара на фротне, записать определенную информацию в новое отдельное поле и потом вывести ее в админке? Этим способом почему то у меня не получается у товаров вывести доп.поля. Может где то ошибся, или там нужно по другому что то делать?..
Александр Мальцев
Александр Мальцев
Привет! Нужно проверить, где-то что-то забыли сделать. В админке проблем не должно быть. С фронта наверно не получится, т.к. ms2form работает дополнительно только с TV. Тут скорее всего только своё писать.
Александр
Александр
Александр, здравствуйте! Как можно в админке вывести поле «изображение», подскажите пожалуйста?
Александр Мальцев
Александр Мальцев
Привет!
Можно так:
page.insert(1,{
  xtype: 'panel'
  ,border: false
  ,bodyStyle: 'margin-top: 10px;'
  ,html: '<img src="/assets/img-1.png" style="max-width: 100%; height: auto;">'
});
Александр
Александр
Здравствуйте! Спасибо. Александр, скажите пожалуйста а как можно добавить своё поле, для добавления изображения к ресурсу?
Александр Мальцев
Александр Мальцев
Привет! Вставить поле для добавления изображения к ресурсу, используя 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
Александр
Александр
Александр, здравствуйте! Огромное спасибо, вывести поле (Изображение) получилось, но как понимаю для работы с ним есть некоторые нюансы?

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

Александр и если возможно, подскажите пожалуйста, как нужно сделать чтобы изображение добавленное к ресурсу в редактировании ресурса, отображалось рядом с полем «image»?
Александр Мальцев
Александр Мальцев
Добрый день!
Тут вроде как обычно:
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']);
// ...
Александр Мальцев
Александр Мальцев
Для того чтобы дополнительно вывести рядом с полем 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
    });
// ...
Александр
Александр
Александр, здравствуйте! Получается я не указал в параметрах поля:
,value: '{$image}'
по этому были проблемы. Огромное Вам спасибо!
Александр
Александр
Я изначально додумался только до того, чтобы использовать поле для вывода изображения, но тогда при редактировании ресурса и выборе изображения не будет обновления изображения на лету, а этот вариант просто идеальный, большое спасибо!
Александр
Александр
Александр, здравствуйте! Пытаюсь вывести поля в компоненте 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?
Александр Мальцев
Александр Мальцев
Александр, CompareList не использовал. Может он это просто не умеет. Если это так, то тогда только разрабатывать свой сниппет.
Александр
Александр
В мануале этого компонента указано (вы можете подключить значения из таблицы msProductFil) и приведён пример с параметром «leftjoin» и «Select» Подключение значения из таблицы msProductFil в CMS MODXАлександр, если теоретически, можно ли c этого примера сделать вывод, что он будет работать с другими полями?
Александр Мальцев
Александр Мальцев
Александр, у меня нет CompareList. В нём наверно нет «modResource.id». Нужно вместо этого поля указать другое.
Александр
Александр
Александр, чтобы уже точно убедится что использовать «CompareList» для своих полей не получится на всякий случай скину ссылку на сниппет CompareList, если у Вас будет время, посмотрите пожалуйста.
Александр Мальцев
Александр Мальцев
Если он у вас используется для сравнения товаров, то «msProduct.id», иначе «modResource.id». Если не получится, то в документации CompareList имеется пример с использованием prepareSnippet. Можете сделать через него.
Александр
Александр
Спасибо!
Александр
Александр
Александр, здравствуйте! Всё реализовал по данному руководству, всё получилось, ещё раз спасибо за данное решение, но есть проблема, плагин почему-то добавляет значения в таблицу базы, разделяя их запятой, пример: «дайвинг, плаванье, лыжи» менял в плагине вот эту строку:

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

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

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

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

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

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

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

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

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

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

2. И не получается вывести в результатах mFilter2, [[!+extend.myhobbies]], как это можно попробовать решить?
Александр
Александр
Александр по поводу первого моего вопроса (1. Не сохраняет в базу значения, если используешь это поле для категории ресурсов, почему так?), получилось решить проблему, указав у всех полей, кроме поля (id) и (resources) По умолчанию NULL, но на сколько это правильно и стоит ли так делать?
Александр Мальцев
Александр Мальцев
Этот пример вставляет на страницу блок после 6 элемента в указанной секции.
1. Не знаю с чем у вас это связано. Если ресурс является контейнером всё сохраняется.
2. Необходимо в сниппет mFilter2 добавить модель extendResource (&loadModels), соединение с таблицей content_extend (&leftjoin) и выбрать нужные поля из таблицы (&select).
Александр Мальцев
Александр Мальцев
Александр, нужно проверить индексы таблицы в базе данных.
Александр
Александр
Александр, спасибо! Первая проблема была из-за не правильной структуры таблицы сейчас всё работает, вторая тоже по моей невнимательности, ещё раз спасибо за помощь.
Александр
Александр
Спасибо!
Александр
Александр
Отличное руководство, спасибо! Скажите пожалуйста, как можно сделать, чтобы в админке к примеру поле level было выпадающим списком, множественный выбор или чекбоксами, аналогично тв?
Александр Мальцев
Александр Мальцев
Спасибо за добрые слова. Информацию по checkbox полю добавил в статью.
Александр
Александр
Огромное спасибо за очень нужную и полезную информацию.
Александр Мальцев
Александр Мальцев
Информацию по остальным двум моментам тоже добавил в статью.
Александр
Александр
Александр, спасибо. Очень нужная и максимально понятная информация.
Aleksandr Dom
Aleksandr Dom
Добрый день.
Не подскажите, как с помощью формы на странице, добавить запись в свою таблицу БД?
Т.е. таблицу сделал. Схему написал. С выводом вроде бы всё понятно. А вот как формой (php или formit) не соображу.
Сеокотов
Сеокотов
есть ли какие то преимущества в скорости работы с этими полями перед TVшками? Или это только для удобства администрирования?
Александр Мальцев
Александр Мальцев
Конечно, есть. Если, например, в проекте используется 7 TV. То для получения их значений для данного ресурса необходимо будет использовать 7 конструкций &leftJoin. И соответственно данный запрос будет выполняться намного дольше, чем, если бы получить все эти значения из одной строки таблицы. В последнем случае понадобится всего один &leftJoin.
Кроме этого используя эту инструкцию, можно установить полям необходимый тип данных, в случае с TV это сделать нельзя, их значение всегда имеет тип mediumtext. А это создаёт трудности для фильтрации и сортировки.
Сергей
Сергей
Сделал компонент 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;
Сергей
Сергей
Сделал, все как написано.
В админке дополнительные поля не отображаются. В журнале ошибок пусто.
Похоже вот это не работает, хотя плагин отрабатывает.
$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
);
Сергей
Сергей
Хм, так поля появились. Значит я где-то накосячил. Буду разбираться.
Сергей
Сергей
А какого типа надо добавить дополнительное поле к ресурсу (например «Ширина») и при редактировании ресурса добавить несколько вариантов значений в это поле, что бы потом на фронтенде можно было с этого поля сделать DropDown List с теми вариантами которые ми определили в админке?
Спасибо.
Александр Мальцев
Александр Мальцев
Добавить текстовое поле 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`]]
Виталий
Виталий
Поясните пожалуйста:
Поле views (количество просмотров) — будет подсчитывать количество просмотров или надо ещё спец.компоненты устанавливать?
Поле level (минимальный уровень доступа к ресурсу) — для чего используется?
Александр Мальцев
Александр Мальцев
Это просто пример как можно организовать добавление дополнительный полей к ресурсу. Поля views, level, keywors приведены для примера. Если нужно, например, вести учёт просмотр ресурсов, то эту логику, конечно, необходимо написать дополнительно.

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