Плагины товаров
Как известно, в таблице ресурсов MODX есть определённое количество полей: pagetitle
, longtitle
, content
и т.д. Если вам нужно что-то дополнительно, то для этого принято использовать ТВ параметры - это "механизм по умолчанию". Он очень гибкий и продвинутый, но имеет ряд недостатков:
- Все поля в БД с типом text. Это означает медленный поиск и сортировку.
- ТВ привязываются к шаблону, без шаблона с ними работать нельзя.
- В них выполняются биндинги @EVAL и @SELECT, которые могут вызывать небезопасный код.
- При выборке ресурсов необходимы дополнительные запросы.
Так как у любого товара должен быть обязательный набор некоторых свойств (цена, артикул, вес и т.д.), в miniShop2 используется дополнительная таблица для них.
В ней все поля имеют нужный тип, расставлены индексы и связи с другими таблицами. В MODX она представлена объектом msProductData, который очень крепко связан с msProduct.
Например, вы можете делать вот так:
if ($data = $modx->getObject('msProductData', 15)) {
$vendor = $product->getOne('Vendor'); // Объект с производителем товара, который привязан к продукту
$options = $product->getMany('Options'); // Массив с объектами опций товара
$files = $product->getMany('Files'); // Массив с объектами картинок товара
$product = $data->getOne('Product'); // Ресурс, к которому привязан объект
}
Причем, объект msProduct как-бы транслирует объекту msProductData запросы. То есть, мы сразу из него может получать свойства товара:
if ($product = $modx->getObject('msProduct', 15)) {
echo $product->get('price');
$product->set('price', 500);
$product->save();
}
Такой дополнительной таблицей очень удобно и приятно пользоваться. Но, количество полей и в этой таблице также ограничено. А что делать, если нам нужно добавить\изменить 10 полей?
Первый вариант очевиден - использовать ТВ параметры. Его никто не забирает, можно пользоваться всегда в своё удовольствие. Но нам больше интересен второй вариант - система плагинов для товаров.
Принцип работы
Первым делом нужно определиться, что плагины\расширения miniShop2 и плагины MODX - две принципиально разные вещи. В чем отличие?
В MODX плагины создаются заранее в дереве элементов и реагируют на события, которые вызывают скрипты. Нет события - нет работы плагина, всё просто.
Плагины miniShop2 - это специальные файлы, положенные в нужные места. Они загружаются всегда, при старте класса ms2, а он в свою очередь стартует при запуске MODX. То есть, плагин MS2 работает постоянно, и то что он делает не нужно дополнительно включать или активировать.
Плагины miniShop2 могут добавлять данные в карту объектов modX::map
и в javascript объект miniShop2.plugin
.
Карта объектов служит для работы PHP логики (получение, сохранение данных в БД), а javascript нужен для добавления\изменения полей в админке.
Таким образом, контроллер плагина должен возвращать массив с двумя ключами:
- map - массив объектов miniShop2 с файлами для загрузки изменений.
- manager - массив ссылок на файлы для загрузки в админке.
В общем виде контроллер плагина выглядит вот так:
<?php
return array(
'map' => array(
'msProductData' => require_once 'msproductdata.inc.php',
),
'manager' => array(
'msProductData' => MODX_ASSETS_URL . 'components/msplcolor/msproductdata.js',
),
);
Целью работы нашего плагина является изменение стандартного поля color в модели товаров. В оригинале, это поле рассчитано под список возможных цветов, что нужно далеко не всем, вот мы и превращаем родной тип json в string.
Расширение модели
Всё нужное для изменения модели мы загружаем из файла msproductdata.inc.php
:
<?php
return array(
'fields' => array(
'color' => null,
),
'fieldMeta' => array(
'color' => array(
'dbtype' => 'varchar',
'precision' => '255',
'phptype' => 'string',
'null' => true,
'default' => null,
),
),
'indexes' => array(
'color' => array(
'alias' => 'color',
'primary' => false,
'unique' => false,
'type' => 'BTREE',
'columns' => array(
'color' => array(
'length' => '',
'collation' => 'A',
'null' => false,
),
),
),
),
);
То есть, мы расширяем модель товара без изменения схемы\модели в исходниках, прямо на лету. Если плагин включен, то у товара одни свойства, если отключен - другие. Изменения\обновления ms2 никак не трогают эти плагины и вы сможете запрограммировать свою уникальную логику.
Для изменения модели товара достаточно всего лишь указать массив параметров. Подробные примеры можно найти в .map файлах MODX и ms2.
Изменение модели MODX не влияет на физическую БД, поэтому нужно изменить тип колонки и в ней, например через SQL запрос:
ALTER TABLE `modx_ms2_products` CHANGE `color` `color` VARCHAR(255) NULL DEFAULT NULL;
Так как в нашем плагине указан индекс по изменённому полю - добавляем и его:
ALTER TABLE `modx_ms2_products` ADD INDEX (`color`);
Расширение админки
А изменение для менеджера мы грузим из msproductdata.js
. В этом файле мы добавляем новый объект с двумя методами в miniShop2.plugin
:
miniShop2.plugin.color = {
// Изменение полей для панели товара
getFields: function () {
return {
color: {
xtype: 'minishop2-combo-autocomplete',
description: '<b>[[+color]]</b><br />' + _('ms2_product_color_help')
}
}
},
// Изменение колонок таблицы товаров в категории
getColumns: function () {
return {
color: {
width: 50,
sortable: false,
editor: {
xtype: 'minishop2-combo-autocomplete',
name: 'color'
}
}
}
}
};
Можно указывать любой стандартный xtype, можно заранее объявить свой собственный, в этом же файле, вы ничем не связаны. В примере используется тип autocomplete из ms2, который дополняет ваш ввод совпадениями из поля color других товаров.
При загрузке страниц админки скрипты ms2 вызовут методы из этого объекта и применят ваши изменения. Так как браузер кэширует javascript файлы, не забудьте почистить его кэш.
Подключение
Для подключения плагинов системе нужно дать только путь к вашему контроллеру. Сделать это можно двумя способами.
Старый, не рекомендуемый - положить свой контроллер в директорию MODX_CORE_PATH . 'components/minishop2/plugins/имяплагина/'
. Он должен выдать пути для подключения изменения модели и админки, так что эти файлы вы вольны класть куда угодно.
Новый, рекомендуемый и удобный для сторонних дополнений - использовать методы API. Регистрация плагина:
if ($miniShop2 = $modx->getService('miniShop2')) {
$miniShop2->addPlugin('msplColor', '{core_path}components/msplcolor/index.php');
}
Нужно указать имя и путь к контроллеру. В пути можно использовать плейсхолдеры Можно использовать плейсхолдеры {base_path}
, {core_path}
и {assets_path}
.
Удаление плагина
if ($miniShop2 = $modx->getService('miniShop2')) {
$miniShop2->removePlugin('msplColor');
}
Все изменения в таблицами БД нужно делать самостоятельно при регистрации и удалении плагинов.
Пример
Система плагинов miniShop2 позволяет выпускать готовые компоненты для удобной установки/удаления новых свойств товаров.
Исходники такого компонента, который меняет поле цветов товара, я выложил для примера на GitHub. Собранный пакет можно скачать там же. Разработчикам будущих плагинов советую обратить внимание на резолверы: один меняет записи в лексиконе, а другой таблицу БД.
Осторожно
При установке компонента очищаются поля color
у товаров! Не нужно экспериментировать на рабочем проекте!