Shopaholic добавить поля

Простой плагин добавления в админку Shopaholic своих полей (в категорию, бренд, оффер или товар)

Upd. 07.05.2021: Плагин добавлен в официальный marketplace OctoberCMS, скачать его можно под названием Additional fields for Shopaholic. Если хотите обновляться автоматически, устанавливайтесь через него.

Для Shopaholic уже есть готовый платный плагин Properties for Shopaholic, советую использовать его. Он поддерживается командой Lovata, это непосредственно разрабочтик Шопаголика.

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

Я уже писал уроки на OctoClub на тему:

Если нужно понять суть еще подробнее, то прошу ознакомиться с этими постами тоже. В этом плагие смысл тот же, но добавлена автоматика. Один раз установил и работает! :)

Механизм работы

Плагин добавляет в существующую таблицу БД Shopaholic'а (товар, бренд или категорию) новое поле. Поэтому в данной версии плагина можно добавлять только простые поля, например текстовое. В следующей версии плагина допишу функционал добавления с возможностью добавления поля с вариантами (выпадающий список, чекбоксы и т.д.)

Часть 1. Работаем с OctoberCMS

Шаг 1. Стартуем

Для работы нам понядобятся новый плагин с компонентом и моделью. Назовем плагин Fields. В консоль пишем:

php artisan create:plugin Site21.Fields
php artisan create:component Site21.Fields Fields
php artisan create:model Site21.Fields Field

Шаг 2. Работа с моделью

Мы должны где-то хранить список полей которые мы создадим. Для этого создаем новую таблицу site21_shopaholic_fields

Создадим в папке плагина папку под названием create_fields_table.php со следующим содержимым:

<?php namespace Site21\Fields\Updates;

use Schema;
use October\Rain\Database\Schema\Blueprint;
use October\Rain\Database\Updates\Migration;

class CreateFieldsTable extends Migration
{
    public function up()
    {
        Schema::create('site21_shopaholic_fields', function (Blueprint $table) {
            $table->engine = 'InnoDB';
            $table->increments('id');
            $table->string('name');
            $table->string('slug');
            $table->string('type');
            $table->string('module');
            $table->boolean('active');
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists('site21_shopaholic_fields');
    }
}


По списку что для чего нужно:

  • name - поле на русском, так его увидет администратор на сайте
  • slug - будет генерироваться автоматически или изменяется ручками. Используется как название поля БД + так мы будем выводить поле в коде.
  • type - тип поля, на данный момент это текст или текстовая область
  • module - куда добавляем поле? в бренд, категорию, товар или торговое предложение.
  • active и timestamps на всякий случай :)

Мы изменили стандартный шаблон наименования таблицы, в поэтому в файле models/Field.php добавим:

public $table = 'site21_shopaholic_fields';

public $rules = [
    'name'      => 'required',
    'slug'      => 'required|unique:site21_shopaholic_fields',
    'type'      => 'required',
    'module'    => 'required',
];

Заодно добавили правила валидации и слаг сделали уникальным.

В файле updates/version.yaml добавим:

1.0.2:
  - Create table with Fields
  - create_fields_table.php

и в консоли запустим:

php artisan october:up

Таким образом мы добавили новую таблицу в БД OctoberCMS.

Шаг 3. Работа с внешней частью

В boot() нашего плагина пишем:

Event::listen('backend.menu.extendItems', function($manager) {
    $manager->addSideMenuItems('Lovata.Shopaholic', 'shopaholic-menu-main', [
        'fields' => [
            'code'  => 'fields',
            'label' => 'Доп. поля',
            'icon'  => 'icon-tags',
            'url'   => Backend::url('site21/fields/fields'),
            'order' => 550,
        ],
    ]);
});

В контроллере (controllerts/Fields.php) заменяем BackendMenu::setContext на:

BackendMenu::setContext('Lovata.Shopaholic', 'shopaholic-menu-main', 'fields');

Таким образом мы ссылку со списком всех полей разместили в сайдбар компонента Шопаголик.

Теперь добавьте новые поля в форму (models/field/fields.yaml):

fields:
    id:
      label: ID
      disabled: true
      hidden: true

    name:
      label: Название поля
      type: text
      span: left
      required: 1

    slug:
        label: Слаг
        span: right
        required: 1
        preset:
          field: name
          type: slug
        type: text

    type:
      label: Тип поля
      span: left
      required: 1
      type: dropdown
      default: text
      context:
          - create
      options:
        text: Текстовое поле
        textarea: Текстовая область

    module:
      label: Модуль
      span: right
      required: 1
      type: dropdown
      default: product
      context:
          - create
      options:
        product: Товар
        offer: Торговое предложение
        category: Категория
        brand: Бренд

    active:
      label: Активное поле
      span: left
      required: 1
      type: switch
      comment: Если выключено, то не выводится в формах
      on: Да
      off: Нет

и на страницу со списком полей (models/field/columns.yaml). Раписывать подробно здесь я не буду, вы можете посмотреть пример в готовом варианте или в документации OctoberCMS.

Шаг 4. Добавляем логику в модель

Наконец-то! Самое интересное :)

Структуру плагина мы построили, теперь нужно добавить немного логики в этот великолепный плагин.

В модель (models/Field.php) добавим следующий код:

// указываем необходимую таблицу в зависимости от выбора куда добавляем поле
function getModuleTable($module){
    $moduleTable = [
        'product'    => 'lovata_shopaholic_products',
        'offer'      => 'lovata_shopaholic_offers',
        'category'   => 'lovata_shopaholic_categories',
        'brand'      => 'lovata_shopaholic_brands',
    ];
    $obTable = $moduleTable[$module];
    return $obTable;
}

public function afterCreate()
{
    $obTable = $this->getModuleTable($this->module);
    if (!Schema::hasTable($obTable) || Schema::hasColumn($obTable, $this->slug)) {
        return;
    }
    
    Schema::table($obTable, function ($table) {
        $type = [
            'text'       => 'string',
            'textarea'   => 'text'
        ];
        $obType = $type[$this->type];
        $table->$obType($this->slug)->nullable();
    });
}


public function afterDelete()
{
    Schema::table($this->getModuleTable($this->module), function ($table) {
        $table->dropColumn($this->slug);
    });
}

public function afterUpdate()
{
    if ($this->slug != $this->original['slug']) {
        Schema::table($this->getModuleTable($this->module), function ($table) {
            $table->renameColumn($this->original['slug'], $this->slug);
        }); 
    }
}

Теперь мы можем добавлять поля, редактировать их и удалять. Ура! Пол дела сделано)

Пока ничего связанного с плагином Shopaholic не было. Это чисто код OctoberCMS, таким образом мы можем добавить любые поля в любые таблицы любого плагина (см. getModuleTable())

Часть 2. Работаем с Shopaholic

Для того чтобы добавить поля в Shopaholic в очередной раз воспользуемся инструкцией официального сайта плагина.

Для примера выведем поля в товары.

Создадим 2 файла. Первый (добавляем поле в форму редактирования товара в админке) по пути: plugins/site21/fields/classes/event/product/ExtendProductFieldsHandler.php:

<?php namespace Site21\Fields\Classes\Event\Product;

use Lovata\Toolbox\Classes\Event\AbstractBackendFieldHandler;
use Lovata\Shopaholic\Models\Product;
use Lovata\Shopaholic\Controllers\Products;
use Site21\Fields\Models\Field;


class ExtendProductFieldsHandler extends AbstractBackendFieldHandler
{
    protected function extendFields($obWidget)
    {
        // Получаем все кастомные поля только для товара
        $fields = Field::where('module', 'product')->where('active', 1)->select('name', 'slug', 'type')->get();
        if($fields) {
            $arAdditionFields = [];
            foreach($fields as $field) {
                $arAdditionFields[$field->slug] = [
                    'label'   => $field->name,
                    'type'    => $field->type,
                ];
            }

            $obWidget->addTabFields($arAdditionFields);
        }
    }

    protected function getModelClass() : string
    {
        return Product::class;
    }
    protected function getControllerClass() : string
    {
        return Products::class;
    }
}

И второй (добавляет в кэш) по пути: plugins/site21/fields/classes/event/product/ExtendProductModel.php:

<?php namespace Site21\Fields\Classes\Event\Product;

use Lovata\Shopaholic\Models\Product;
use Site21\Fields\Models\Field;

class ExtendProductModel
{
    public function subscribe()
    {
        Product::extend(function ($obProduct) {
        $fields = Field::where('module', 'product')->where('active', 1)->select('slug')->get();
            if($fields) {
                $array = [];
                foreach($fields as $field) {
                    $obProduct->fillable[] = $field->slug;
                    $array[] = $field->slug;    
                }
                $obProduct->addCachedField($array);
            }
        });
    }
}

Ну и в boot() plugin.php подцепим файлы:

use Site21\Fields\Classes\Event\Product\ExtendProductFieldsHandler;
use Site21\Fields\Classes\Event\Product\ExtendProductModel;
--
Event::subscribe(ExtendProductFieldsHandler::class);
Event::subscribe(ExtendProductModel::class);

Все готово!

Теперь у товара появились новые поля, выводить их нужно также как и любые другие поля плагина Shopaholic для OctoberCMS.

Как добавить поля в оффер, бренд или категорию я показывать не буду. Это все Вы найдете в документации. Нужнео лишь немного добавить код с запросом.

Либо Вы можете скачать готовый плагин по ссылке ниже.

В дальнейшем плагин будет поддерживаться, новые версии выкладываться на GitHub

Пример готового плагина

oc-shopaholic-fields.zip

Опубликовано 4 мая 2021 г. в категориях: October CMS Shopaholic

Если Вам необходимо внедрить данную разработку на свой проект, свяжитесь со мной, обсудим цену и срок.

Связаться со мной Fill 1