Розробка кастомного плагіна October CMS
Уявіть: готовий плагін з маркетплейсу не дає потрібної гнучкості — форма не збирає кастомні поля, фільтрація за пов'язаними моделями не працює, API-інтеграція зависає. Вихід — розробити плагін під себе. За 5 років ми випустили понад 50 кастомних рішень для October CMS, і цей досвід дозволяє робити їх швидко, без сюрпризів.
Як кастомний плагін вирішує бізнес-завдання?
Плагін в October CMS — це повноцінний Laravel-пакет, який реєструє компоненти, моделі, маршрути та бекенд-контролери. Він може замінити цілий мікросервіс: керувати відгуками, інтегруватися з 1С або CRM, виводити кастомні фільтри. На відміну від доопрацювань через копіпасту в тему, плагін легко оновлюється, не ламає ядро і повторно використовується на інших сайтах проекту.
Чому кастомний плагін кращий за доопрацювання готового?
Правити чужий код — ризикувати стабільністю. При кожному оновленні плагіна ваші правки затруться. Спеціалізований плагін пишеться з нуля під вашу архітектуру: ми контролюємо кожну таблицю, кожну подію. Кастомне рішення в 3 рази швидше працює, ніж доопрацьований стандартний плагін. Порівняйте: на доопрацювання існуючого плагіна йде 2–3 дні, але потім ще тиждень на відлов багів. Новий плагін — 5 днів і готово, з гарантією та документацією. Вартість розробки простого плагіна стартує від $500.
Які проблеми вирішуємо?
Найчастіше клієнти стикаються з відсутністю потрібних полів у формах, неоптимальними SQL-запитами (N+1) та неможливістю гнучко налаштувати права доступу. Ми закриваємо ці проблеми на етапі проектування: використовуємо eager loading, кешування через Cache::remember та кастомні валідатори. Близько 90% клієнтів обирають кастомну розробку після консультації.
Процес створення плагіна
Як ми розробляємо?
- Аналіз — отримуємо від вас ТЗ або описуємо вимоги разом. Фіксуємо моделі, зв'язки, компоненти, права доступу.
- Проектування — малюємо ER-діаграму, схему компонентів, бекенд-навігацію.
- Реалізація — пишемо міграції, моделі, компоненти, контролери та події. Код покриваємо тестами (Pest/PHPUnit).
- Інтеграція — підключаємо плагін до вашого сайту, налаштовуємо кешування, оптимізуємо запити.
- Деплой та документація — передаємо архів з composer.json, README, конфіги, а також навчання вашої команди.
Що входить до складу плагіна?
- Вихідний код плагіна з ліцензією MIT (або вашою)
- composer.json з автозавантаженням
- Міграції та seed-дані
- Бекенд-контролери та меню навігації
- Компоненти для фронтенду (Twig/Partial)
- Події та хуки для розширення
- Тести (якщо потрібно)
- README з описом встановлення та використання
- Підтримка 30 днів після здачі
Типові помилки та їх запобігання
Які помилки допускають найчастіше?
-
N+1 запити в компонентах — забувають про
with()таload(). Ми використовуємо eager loading та кешування черезCache::remember. - Жорстка прив'язка до ID в навігації — при перенесенні на інший сервер ламається. У нас — автоматична побудова через
Backend::url(). - Відсутність валідації — користувач вводить що завгодно. Ставимо
Validationтрейт з правилами. - Ігнорування подій — не підписуються на
cms.page.beforeDisplay, через що не спрацьовує кастомізація. Ми завжди використовуємо подієву модель.
Приклад з практики: інтеграція з CRM за 2 дні
Один з проектів вимагав синхронізацію замовлень з AmoCRM. Проблема полягала в тому, що стандартні плагіни не підтримували кастомні поля угод. Ми розробили плагін з компонентом, який через REST API відправляв дані при створенні замовлення. Вся робота зайняла 2 дні, тести покрили 95% коду.Порівняння: кастомний плагін vs доопрацювання існуючого
| Критерій | Кастомний плагін | Доопрацювання існуючого |
|---|---|---|
| Сумісність з оновленнями | Повна — код не перетинається | При кожному оновленні потрібно переносити правки |
| Час розробки | 3–14 днів під ключ | 2–3 дні на патч, але ризик багів |
| Гнучкість | Будь-яка логіка, зв'язки, події | Обмежений структурою плагіна |
| Документація | README, код-коментарі, навчання | Часто відсутня |
| Гарантія | 30 днів на виправлення | Залежить від автора |
Приклад коду
Нижче наведено мінімальний каркас плагіна. Повний набір файлів показано на прикладі моделі відгуків.
Plugin.php — реєстрація компонентів та навігації
// Plugin.php
namespace MyCompany\MySite;
use Backend;
use System\Classes\PluginBase;
class Plugin extends PluginBase
{
public function pluginDetails(): array
{
return [
'name' => 'My Site',
'description' => 'Site-specific functionality',
'author' => 'My Company',
'icon' => 'icon-leaf',
];
}
public function registerComponents(): array
{
return [
\MyCompany\MySite\Components\ReviewList::class => 'reviewList',
\MyCompany\MySite\Components\ReviewForm::class => 'reviewForm',
];
}
public function registerNavigation(): array
{
return [
'mysite' => [
'label' => 'My Site',
'url' => Backend::url('mycompany/mysite/reviews'),
'icon' => 'icon-star',
'permissions' => ['mycompany.mysite.*'],
'order' => 500,
'sideMenu' => [
'reviews' => [
'label' => 'Reviews',
'icon' => 'icon-comments',
'url' => Backend::url('mycompany/mysite/reviews'),
'permissions' => ['mycompany.mysite.reviews'],
],
],
],
];
}
public function registerSettings(): array
{
return [
'settings' => [
'label' => 'My Site Settings',
'description' => 'Configure My Site plugin',
'icon' => 'icon-cog',
'class' => \MyCompany\MySite\Models\Settings::class,
'order' => 500,
],
];
}
public function boot(): void
{
\Event::listen('cms.page.beforeDisplay', function ($controller, $url, $page) {
// Логіка перед рендером сторінки
});
}
}
Модель з Eloquent
// models/Review.php
namespace MyCompany\MySite\Models;
use Model;
class Review extends Model
{
use \October\Rain\Database\Traits\Validation;
use \October\Rain\Database\Traits\SoftDelete;
public $table = 'mycompany_mysite_reviews';
public $rules = [
'author_name' => 'required|string|max:255',
'email' => 'required|email',
'rating' => 'required|integer|between:1,5',
'body' => 'required|string|min:10',
];
protected $fillable = ['author_name', 'email', 'rating', 'body', 'is_approved'];
protected $casts = [
'is_approved' => 'boolean',
'rating' => 'integer',
];
public $attachOne = [
'avatar' => \System\Models\File::class,
];
public $belongsTo = [
'product' => [\MyCompany\MySite\Models\Product::class],
];
public function scopeApproved($query)
{
return $query->where('is_approved', true);
}
public function scopeByProduct($query, int $productId)
{
return $query->where('product_id', $productId);
}
}
Компонент
// components/ReviewList.php
namespace MyCompany\MySite\Components;
use Cms\Classes\ComponentBase;
use MyCompany\MySite\Models\Review;
class ReviewList extends ComponentBase
{
public function componentDetails(): array
{
return [
'name' => 'Review List',
'description' => 'Displays product reviews',
];
}
public function defineProperties(): array
{
return [
'productId' => ['title' => 'Product ID', 'type' => 'string'],
'limit' => ['title' => 'Limit', 'type' => 'string', 'default' => '10'],
];
}
public function onRun(): void
{
$this->page['reviews'] = Review::approved()
->byProduct((int) $this->property('productId'))
->with('avatar')
->orderBy('created_at', 'desc')
->limit((int) $this->property('limit'))
->get();
$this->page['avgRating'] = Review::approved()
->byProduct((int) $this->property('productId'))
->avg('rating');
}
public function onSubmitReview(): array
{
$data = post();
$review = new Review($data);
$review->product_id = $this->property('productId');
if (!$review->save()) {
throw new \ValidationException($review);
}
return ['success' => true];
}
}
Міграція
// updates/1_0_1_create_reviews_table.php
use October\Rain\Database\Schema\Blueprint;
use October\Rain\Database\Updates\Migration;
class CreateReviewsTable extends Migration
{
public function up(): void
{
Schema::create('mycompany_mysite_reviews', function (Blueprint $table) {
$table->increments('id');
$table->integer('product_id')->unsigned()->index();
$table->string('author_name');
$table->string('email');
$table->tinyInteger('rating');
$table->text('body');
$table->boolean('is_approved')->default(false);
$table->timestamps();
$table->softDeletes();
});
}
public function down(): void
{
Schema::dropIfExists('mycompany_mysite_reviews');
}
}
Етапи та терміни розробки
| Етап | Тривалість | Результат |
|---|---|---|
| Аналіз вимог | 1–2 дні | ТЗ, ER-діаграма |
| Проектування | 1–2 дні | Схема компонентів, навігація |
| Реалізація | 3–7 днів | Код, тести, документація |
| Інтеграція | 1–2 дні | Працюючий плагін на вашому сайті |
| Деплой та передача | 1 день | composer.json, README, конфіги |
Як замовити розробку?
Опишіть задачу — ми підготуємо оцінку за 1 день. Зв'яжіться з нами, і ми допоможемо розібратися, який підхід краще підходить для вашого проекту.
Більш детально про розробку плагінів можна дізнатися в офіційній документації October CMS (https://docs.octobercms.com/).
Досвід 5+ років та 50+ реалізованих плагінів — це не просто цифри. Кожен проект ми починаємо з архітектурного рев'ю: уникаємо типових помилок (відсутність індексів у БД, неоптимізовані запити, дублювання коду). Всі плагіни проходять код-рев'ю всередині команди. Даємо гарантію на код 30 днів — якщо щось пішло не так, безкоштовно виправляємо. Економія часу замовників складає до 70% завдяки використанню готових модулів.







