---
title: "MKSine: CMS на базі Filament із плагінами, темами та блоками"
url: https://laravelukraine.com/blog/mksine-cms-na-bazi-filament-iz-plaginami-temami-ta-blokami
date: 2026-09-02
source: https://laravel-news.com/mksine-filament-cms?utm_medium=feed&utm_source=feedpress.me&utm_campaign=Feed%3A+laravelnews
---

# MKSine: CMS на базі Filament із плагінами, темами та блоками

Багато Laravel-проєктів потребують маркетингового сайту поруч із застосунком - зі сторінками, які може оновлювати редактор, меню, яке можна переупорядковувати, та місцем для зберігання зображень. Filament покриває адмін-панель, а контентний шар зазвичай доводиться писати вручну. MKSine, розроблений Міраном Салехі, надає готове рішення: сторінки, пости, категорії, конструктор сторінок на основі блоків, теми, меню, медіабібліотеку та систему плагінів із життєвим циклом встановлення та активації. Пакет орієнтований на Filament 4 та 5.

## Встановлення та налаштування

Встановіть пакет і налаштуйте панель Filament:

```bash
composer require miran/mksine
php artisan filament:install --panels
```

Після цього потрібно вручну відредагувати два файли. У `AdminPanelProvider` зареєструйте `MksinePlugin::make()` на панелі та видаліть блок `->pages([Dashboard::class])`, оскільки MKSine реєструє власну панель керування за адресою `/admin`, і виконання обох призводить до помилки 500. У `routes/web.php` видаліть стандартний обробник `Route::get('/')`, оскільки MKSine обслуговує головну сторінку через активну тему. Тільки після цього запустіть інсталятор і створіть перший обліковий запис:

```bash
php artisan mksine:install --migrate
php artisan mksine:create-super-admin
```

Команда `mksine:install` публікує конфігурацію, виконує міграції та запускає `shield:generate --all`, який сканує панель у тому стані, в якому вона зареєстрована на той момент. Якщо `MksinePlugin` ще не додано до панелі, він не створить жодних дозволів MKSine, і для відновлення доведеться вручну запустити `php artisan shield:generate --panel=admin --all`.

## Авторизація та права доступу

Авторизація працює через Filament Shield, який пакет підключає як залежність разом із перемикачем мов та полем select-tree. Shield записує класи політик у хост-застосунок під `App\Policies`, а MKSine прив'язує їх до власних моделей через `Gate::policy()`. Прив'язка захищена `class_exists()`, тому модель, політика якої ніколи не генерувалася, залишається без контролю, і всі операції з нею дозволені.

Інсталятор також переписує `app/Models/User.php`, додаючи контракт `FilamentUser` від Filament та трейт `InteractsWithMksine` від MKSine. Спочатку створюється резервна копія з міткою часу, і якщо патч не вдається застосувати, меню адміністратора показує лише панель керування.

## Система плагінів

Плагін MKSine - це директорія під `plugins/{id}/` з маніфестом `plugin.php` та класом, що реалізує `PluginInterface`. Маніфест визначає id, версію, namespace та клас плагіна:

```php
return [
 'id' => 'notes',
 'name' => 'Notes',
 'description' => 'Demo plugin',
 'version' => '0.1.0',
 'author' => 'Your Name',
 'namespace' => 'Plugins\\Notes',
 'plugin_class' => Plugins\Notes\NotesPlugin::class,
];
```

Генераторні команди створюють каркас плагіна, реєструють його та додають модель і ресурс Filament:

```bash
php artisan mks-plugin:make notes --author="Your Name"
php artisan mks-plugin:discover
php artisan mks-plugin:install notes
php artisan mks-plugin:activate notes
php artisan mks-plugin:make-model notes Note --migration
php artisan mks-plugin:migrate notes
php artisan mks-plugin:make-resource notes Note --model=Note
```

Виявлення сканує кожен `plugin.php` і кешує реєстр у `bootstrap/cache/mks_plugins_discovery.php`, щоб наступні завантаження читали кеш замість файлової системи. Після активації плагін завантажує свої ресурси, сторінки та віджети Filament із канонічних шляхів без жодної реєстрації на панелі. Його міграції залишаються в дереві плагіна і виконуються лише через `mks-plugin:migrate {id}`, а скомпільовані ресурси публікуються в `public/plugins/{id}/`.

Таблиця `mks_plugins` зберігає стан кожного плагіна: discovered, installed, active, inactive або failed. Якщо `boot()` плагіна викидає виняток, захисник завантаження позначає його як невдалий і записує повідомлення в `mks_plugins.boot_error`, а решта застосунку продовжує працювати. Деактивація плагіна зупиняє `boot()` і приховує його екрани адміністратора, залишаючи таблиці та рядки на місці. Дані видаляються лише при видаленні з опцією `--delete-data`.

## Хуки та точки розширення

Точки розширення поділяються на дві родини. Хуки виявлення - це класи-слухачі, які сканує `php artisan mks:discover`, записуючи по одному рядку на слухача в `mks_hooks`. Рядок також робить слухача видимим в адміністратора, де суперадмін може ввімкнути або вимкнути його чи змінити пріоритет. Слухачі, позначені як системні, завжди виконуються. Потрібно повторно запускати виявлення після кожної зміни коду.

Хуки виконання - це замикання або зворотні виклики класів, зареєстровані через фасад `Hooks::` всередині `boot()` плагіна. Вони залишаються в пам'яті, перереєструються при кожному запиті і ніде не відображаються в адміністратора. Відношення ресурсів, віджети, дії заголовка сторінки та фільтри виконання доступні лише таким чином. Видалення плагіна прибирає його хуки виконання.

Імена слухачів з підстановочними знаками, такі як `post.*`, не підтримуються. Фільтри виконання, зареєстровані через `Hooks::addFilter()`, не потрапляють у `mks_hooks`, тому їх не можна перемикати. Розширення форм і таблиць завжди виконуються синхронно. Лише `FormHookManager` перехоплює винятки слухача; хуки таблиць, ресурсів і сторінок дозволяють винятку поширюватися. Для важчої роботи слухач може реалізувати `QueueableHookEventInterface` і поставити себе в чергу.

## Блоки конструктора сторінок

Блоки конструктора сторінок розширюють `BaseBuilderComponent`. Клас описує, як блок з'являється у вибірці, схему Filament для редагування та шаблон Blade для рендерингу на сайті:

```php
use Miran\Mksine\Core\PageBuilder\BaseBuilderComponent;

class PriceTableBlock extends BaseBuilderComponent
{
 public static function getType(): string
 {
 return 'acme_price_table';
 }

 public static function getName(): string
 {
 return __('acme-pricing::builder.price_table.name');
 }

 public static function getIcon(): string
 {
 return 'heroicon-o-table-cells';
 }

 public static function getCategory(): string
 {
 return self::CATEGORY_SECTIONS;
 }

 public static function getSchema(): array
 {
 return [
 TextInput::make('title')->maxLength(255),
 Repeater::make('plans')
 ->schema([
 TextInput::make('name')->required()->maxLength(80),
 TextInput::make('price')->required()->maxLength(40),
 Toggle::make('featured')->default(false),
 ])
 ->reorderable(),
 ];
 }

 public static function getDefaultData(): array
 {
 return ['title' => '', 'plans' => []];
 }

 public static function getRenderView(): string
 {
 return 'acme-pricing::builder.price-table';
 }
}
```

Автоматичного виявлення блоків немає. Кожен потрібно зареєструвати в `ComponentRegistry`, зазвичай із `boot()` плагіна:

```php
use Miran\Mksine\Core\PageBuilder\ComponentRegistry;

app(ComponentRegistry::class)->register(PriceTableBlock::class);
```

Редактори перетягують блок на сторінку, а дерево зберігається в колонці `builder_payload` сторінки - JSON-колонка, приведена до масиву на моделі `Page`. Шаблон отримує масив `$data` блоку плюс `$children` для блоків-контейнерів. Сторінка, остання редагована рік тому, може містити payload, написаний під старішу схему, тому шаблон повинен встановлювати значення за замовчуванням для кожного ключа. Коли тип не зареєстрований або `getRenderView()` вказує на неіснуючий шаблон, рендерер перевіряє `View::exists()` і повертається до жовтої панелі «Unknown component type:», що вказує тип, який не вдалося вирішити.

Блоки не мають окремих дозволів Shield. Будь-хто, хто може редагувати сторінку, може додати будь-який зареєстрований блок, тому блок, що відкриває щось чутливе, повинен захищати свій відрендерений вивід.

## Вкладки налаштувань

Сторінка налаштувань має основні вкладки для General та Permalinks, а Geo на власній сторінці. Плагіни додають вкладки через `SettingsTabManager`, а не редагуванням класу сторінки:

```php
use Miran\Mksine\Core\Hooks\SettingsTabManager;

app(SettingsTabManager::class)->registerTab(
 id: 'acme_seo',
 label: fn () => __('acme-seo::settings.tab_label'),
 schema: [
 TextInput::make('acme_seo_meta_description')->maxLength(320),
 Toggle::make('acme_seo_enable_og_tags')->default(true),
 ],
 sortOrder: 50,
);
```

Вкладки - це лише групування інтерфейсу. Кожне поле зберігається в таблицю `settings` під власним ім'ям, а `mks_setting('acme_seo_meta_description')` зчитує його з кешем на запит. Оскільки ключ - це ім'я поля, плагін, що визначає `site_name`, перезаписує основний `site_name`, тому документація рекомендує префіксувати кожне ім'я поля плагіна. Збереження перезаписує негайно, без чернетки та аудиту.

## Теми, меню та медіа

Тема - це або пакет, або директорія під `themes/{id}/`. Одна тема активна одночасно, вона надає шаблони Blade для вітрини разом із опублікованими CSS і JS, які суперадмін може редагувати з панелі.

Конструктор меню обробляє вкладеність та перетягування для зміни порядку. Елементи походять зі сторінок, постів, категорій або користувацьких URL, і кожне меню призначається на місце теми, таке як header або footer.

Медіабібліотека - це власне сховище файлів пакета на одному диску, а не обгортка навколо `spatie/laravel-medialibrary`. Таблиця з'єднання `media_attachments` прикріплює файли до будь-якої моделі, а форми вибирають із бібліотеки через компонент `MediaPicker`. Завантаження отримують мініатюри small, medium і large, а оптимізація зображень увімкнена за замовчуванням, хоча цей крок вимагає встановлення бінарних оптимізаторів, таких як jpegoptim, на сервері.

## Переклади та консоль адміністратора

Ви можете редагувати файли перекладів для застосунку, плагінів і тем на панелі за мовою та файлом.

Сторінка консолі, обмежена для суперадмінів, виконує дозволений набір команд Artisan і Composer з живим виведенням і історією виконаних команд.

## Вимоги та ліцензія

MKSine вимагає PHP 8.2, Laravel 11 та Filament 4 або 5. Filament 5 підвищує вимоги до Laravel 11.28, Livewire 4 та Tailwind 4. Це плагін спільноти, не розроблений командою Filament. Поточний тег - v1.5.1, тому читайте вихідний код перед розміщенням на production-сайті. Код разом із документацією, що охоплює розробку плагінів, створення блоків, розгортання та оновлення, доступний на GitHub.
