Skip to content
  1. Компоненты
  2. miniShop2
  3. Разработка
  4. Плагины товаров

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

Как известно, в таблице ресурсов MODX есть определённое количество полей: pagetitle, longtitle, content и т.д. Если вам нужно что-то дополнительно, то для этого принято использовать ТВ параметры - это "механизм по умолчанию". Он очень гибкий и продвинутый, но имеет ряд недостатков:

  • Все поля в БД с типом text. Это означает медленный поиск и сортировку.
  • ТВ привязываются к шаблону, без шаблона с ними работать нельзя.
  • В них выполняются биндинги @EVAL и @SELECT, которые могут вызывать небезопасный код.
  • При выборке ресурсов необходимы дополнительные запросы.

Так как у любого товара должен быть обязательный набор некоторых свойств (цена, артикул, вес и т.д.), в miniShop2 используется дополнительная таблица для них.

В ней все поля имеют нужный тип, расставлены индексы и связи с другими таблицами. В MODX она представлена объектом msProductData, который очень крепко связан с msProduct.

Например, вы можете делать вот так:

php
if ($data = $modx->getObject('msProductData', 15)) {
  $vendor = $product->getOne('Vendor'); // Объект с производителем товара, который привязан к продукту
  $options = $product->getMany('Options'); // Массив с объектами опций товара
  $files = $product->getMany('Files'); // Массив с объектами картинок товара
  $product = $data->getOne('Product'); // Ресурс, к которому привязан объект
}

Причем, объект msProduct как-бы транслирует объекту msProductData запросы. То есть, мы сразу из него может получать свойства товара:

php
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
<?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
<?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 запрос:

sql
ALTER TABLE `modx_ms2_products` CHANGE `color` `color` VARCHAR(255) NULL DEFAULT NULL;

Так как в нашем плагине указан индекс по изменённому полю - добавляем и его:

sql
ALTER TABLE `modx_ms2_products` ADD INDEX (`color`);

Расширение админки

А изменение для менеджера мы грузим из msproductdata.js. В этом файле мы добавляем новый объект с двумя методами в miniShop2.plugin:

js
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. Регистрация плагина:

php
if ($miniShop2 = $modx->getService('miniShop2')) {
  $miniShop2->addPlugin('msplColor', '{core_path}components/msplcolor/index.php');
}

Нужно указать имя и путь к контроллеру. В пути можно использовать плейсхолдеры Можно использовать плейсхолдеры {base_path}, {core_path} и {assets_path}.

Удаление плагина

php
if ($miniShop2 = $modx->getService('miniShop2')) {
  $miniShop2->removePlugin('msplColor');
}

Все изменения в таблицами БД нужно делать самостоятельно при регистрации и удалении плагинов.

Пример

Система плагинов miniShop2 позволяет выпускать готовые компоненты для удобной установки/удаления новых свойств товаров.

Исходники такого компонента, который меняет поле цветов товара, я выложил для примера на GitHub. Собранный пакет можно скачать там же. Разработчикам будущих плагинов советую обратить внимание на резолверы: один меняет записи в лексиконе, а другой таблицу БД.

Осторожно

При установке компонента очищаются поля color у товаров! Не нужно экспериментировать на рабочем проекте!