Многие помнят многострадальный MODx и его фичи в виде TV полей. Когда мы создавали ресурсы и крепили эти поля к шаблонам. Многие новички в Октябре хотят видеть подобный функционал, но не могут его реализовать, потому, что не понимают работать с API October CMS. В этой статье мы создадим плагин простого каталога и сделаем интерфейс закрепления произвольных полей к категориям. Что бы в запись из выбранной категории можно было завести свои поля форм.

Как создать плагин в October CMS

Начнем с формальностей. Я знаю, что многие уже знают как это делается, но не бомбите и промотайте ниже. Так как инструкция предназначена для всех существ из пищевой цепи разработчиков, то объяснять буду в стиле повествования - "Для чайников".

Самый простой и наглядный способ создания плагина на Октябре - это заюзать плагин Rainlab.Builder. Установить его можно напрямую из системы.

Обязательно картинка, ведь инструкция для новичков!

Я боле предпочитаю использовать ssh консоль и php artisan, посмотреть команды вы можете тут, дальше я буду объяснять на примере Билдера.

Приступаем к созданию нашего каталога для October CMS. После установки Builder у нас появится новая вкладка с именем Builder как бы странно это не звучало. Открываем ее и видим необходимый нам интерфейс. Первым делом вы увидите информацию в красной вкладке с сообщением Plugin is not selected. И это вполне логично так как нам необходимо нажать на стрелку, что бы выбрать или создать плагин.

Стрелка, что бы вы не мучились в ее поисках

Открываем стрелку и нажимаем кнопку - create plugin. Откроется модальное окно с полями ввода где:

  • Name - название плагина
  • Author - имя автора

При вводе имени автора и названия плагина, неймспейсы будут сгенерированы автоматически, однако при желании можете их назвать по другому. Вкладка description содержит поле описания. Оно не обязательно к заполнению.

Пример интерфейса создания плагина

Создание таблиц, связи моделей плагина

Теперь нам необходимо заранее сесть и подумать над архитектурой вашего плагина. Делать это проще всего используя обычный лист бумаги и карандаш. Я лишь расскажу вкратце какую схему мы будем использовать. В качестве примера я использую свой стендовый плагин Catdesign.Catalog

Требуемые таблицы в бд:

  • catdesign_catalog_products
  • catdesign_catalog_category
  • catdesign_catalog_fields
  • catdesign_catalog_categories_fields

Требуемые модели:

  • Товар (Product.php)
  • Категория (Category.php)
  • Произвольное поле (Field.php)

Как видите таблицы 4, а модели всего 3. Как же так вышло. Таблица catdesign_catalog_categories_fields служит для осуществления связи многие ко многим, из названия логически понятно categories_fields. То есть данная таблица содержит первичные ключи категорий и кастомных полей, что бы создать между ними связь.

Схема модели, таблицы и связи между ними

Реализуем данную схему. Газуем в билдер и запиливаем таблицы:

Таблица для модели Product.php - tag_id удалить, он нам не нужен
Таблица для модели Category.php
Таблица для модели Field.php
Связующая таблица для связи многие ко многим для моделей Category.php и Field.php

Обратите внимание, что в левой колонке есть таблица catdesign_catalog_tags, она нам не нужна, просто мне было лень ее удалять. Поэтому создавать ее не нужно.

После создания таблиц топаем во вкладку Models и создаем модели для каждой таблицы.

Пример интерфейса создания моделей

После нажатия кнопки add у вас появится модальное окно. Где:

  • Class name - имя класса модели
  • Database table - с какой таблицей класс ассоциирован
  • Add timestamp support - добавить поддержку временных меток (когда создано) created_at, (когда обновлено) updated_at, что бы все работало нормально в таблице должны быть эти колонки.
  • Add soft deleting support - добавить поддержку временной метки (когда удалено) deleted_at. Аналогично выше, должна быть эта колонка. Смысл в том что запись не будет удалиться из базы, но если установлена временная метка deleted_at, то она ведет себя как удаленная.

После того, как модели созданы им нужно создать конфиги .yaml с параметрами для отрисовки списков и форм. Я думаю тут объяснять нет смысла, так как интерфейс очень понятен. Я лишь объясню некоторые моменты, после того как создадим связи. Но важно, что бы массив полей модели Field.php соответствовал параметрам поля для форм.

Type и Label как в ключи как на картинке по соседству

Перейдем к созданию вышеупомянутых связей. Тема довольно обширная и объяснять все до деталей я не буду, так как у нас экспресс гайд. Почитать инфу можно по этой ссылке на документацию.

Переходим в код и ищем наши модели. Если все сделано правильно, то по пути /plugins/catdesign/catalog/models будут лежать наши модельки. Идем в модель продукт (Product.php) и пишем это.

public $belongsTo = [
        'category' => 'Catdesign\Catalog\Models\Category'
];

Связь один ко многим.

Это свойство модели. На русском можно понять это так - модель (Product.php) принадлежит к модели (Category.php). В массиве данных
[ ключ => значение ] где ключ будет алиасом к которому мы будем обращаться, в значение неймспейс модели.
Должно получится примерно такое

Далее таких подробных картинок не будет ибо статья и так сильно растянута. Я думаю вы в состоянии добавить поля и списки самостоятельно.

Идем в модель Category.php и добавляем следующее:

public $belongsToMany = [
        'custom_fields' => [
            'Catdesign\Catalog\Models\Field',
            'table'    => 'catdesign_catalog_categories_fields',
            'otherKey'      => 'field_id',
            'key' => 'category_id'
        ]
 ];

Идем в модель Field.php и добавляем следующее:

public $belongsToMany = [
        'categories' => [
            'Catdesign\Catalog\Models\Category',
            'table'    => 'catdesign_catalog_categories_fields',
            'otherKey'      => 'category_id',
            'key' => 'field_id'
        ]
];

Многие ко многим.

По-русски примерно понимать это так. Field принадлежит многим Category. Как и в свойстве, где связь один ко многим мы указываем алиаса, неймспейс, а так же дополнительно таблицу в которую будут записываться ключи и название этих ключей соответственно.

Создание конфигурации полей форм моделей

Билдер поможет вам создать нужные поля форм, но нам нужно сделать поля типа relation. Что бы, например в продукте указать к какой категории он относится.

Поэтому идем в папку конфигов модели product и открываем field.yaml и добавляем поле:

Добавляем поле category в models/product

Сохраняем, идем дальше. Теперь для отображения списка выбора кастомных полей в категории нам необходимо добавить поле с типом partial в fields.yaml модели Category.php

Добавляем поле custom_fields в models/category

Если поле category у нас будет выводиться в виде простого селекта, то в связанном поле custom_fields мы будем использовать relation manager. Но об этом чуть позднее, как только мы создадим контролеры.

Создание контролеров

Перед тем как создать контроллеры, сначала зайдите во вкладку меню и создайте его. В меню у вас будет 4 пункта.

Пример созданного меню

Теперь нам нужно создать 3 контроллера Products.php, Fields.php, Categories.php. Идем во вкладку контролеры и нажимаем add

  • Controller name - имя контроллера
  • List controller behavior - добавить страницу для отображения списка записей
  • Form controller behavior - добавить интерфейс для создания, изменения и удаления записи
  • Reorder controller behavior - добавить возможность сортировки (то есть изменение порядка записей)

Создаем все необходимые контролеры, потом возвращаемся во вкладку меню и указываем пути в ссылках.

Теперь если обновить страницу, то у нас должен появится новый раздел в меню - Каталог.

Теперь нам нужно заставить работать связь многие ко многим через relation manager. Идем в контролеры и открываем файл Categories.php. Добавляем в него следующие строчки.

Настройка контроллера для использования relation manager

Это подключит наш relation manager, в свойстве $relationConfig указываем путь к созданному конфигу. Конфиг должен находится в папке контролера.

# ===================================
#  Relation Behavior Config
# ===================================

custom_fields:
  label: Дополнительные поля
  view:
    list: $/catdesign/catalog/models/field/columns.yaml
  manage:
    list: $/catdesign/catalog/models/field/columns.yaml
  pivot:
    form: $/catdesign/catalog/models/field/fields.yaml

Содержимое для файла config_relation.yaml. Более подробная информация по relation manager

Далее необходимо создать рядом с config_relation.yaml в этой же папке файл custom_fields.htm Мы указывали на него в fields.yaml модели Category.php когда создавали формы. Содержимое custom_fields.htm:

relationRender('custom_fields') ?>

Теперь зайдем в интерфейс плагина в админке и создадим пару кастомных полей. Теперь если мы зайдем в контроллер категорий и создадим новую то, увидим, что-то такое.

Но это еще не все, мы создали только интерфейс для крепления полей к категории, нужно еще их вывести в контроллере.

Для этой задачи мы должны воспользоваться расширением контроллера. Расширять будем контроллер Products.php так как именно туда нам нужно вывести наши поля.

Для вывода полей нужно написать в контроллере Products.php следующее:

Мы используем метод October CMS formExtendFields($form). В методе проверяем существует ли переменная или нет, на тот случай если запись только создается. Далее мы добавляем поля через addFields передавая в параметр массив наших полей.

Результат страданий

На этом я хочу остановится, так как уже нет сил писать дальше. Да и никто не будет читать. Результатом этих манипуляций, будет возможность добавлять произвольные поля записям через их категории.

Например категория топоры имеет поле дамаг, ширина лезвия.

А категория телефоны имеет поля процессор, экран

Вы создаете поля дамаг, ширина лезвия, процессор, экран и привязываете к своим категориям. Соответственно если товар в этой категории, то он получает инклюд определенных полей. То что мы сделали выше достаточно для того, что бы отобразить эти интерфейсы и продемонстрировать работу этой концепции.

Но прежде чем это заработает вам нужно решить вопрос как вы будете сохранять эти поля. Вариантов масса. В таблицу продукта в JSON формате или создать отдельную таблицу fields_values. Решать вам. А напоследок пара скринов.

Интерфейс крепления полей к категории через relation manager

Интерфейс добавления товара прикрепленного к категории

На этом все, вряд ли до этого момента кто-то дочитал. Но если ты тут... Знай, что ты терминатор. Возможно в будущем переработаю статью, что бы ее укоротить и упростить. Всем спасибо!