Плагины товаров

02 июня 2016, 10:29

Как известно, в таблице ресурсов 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 у товаров! Не нужно экспериментировать на рабочем проекте!


Следующий документ
Скрипты и стили