Блоки
Блок — переиспользуемая единица контента: hero-баннер, преимущества, форма обратной связи, галерея. Страница собирается из блоков в конструкторе или через API.
Структура блока
Блок описывается в двух местах:
| Где | Что хранится |
|---|---|
БД (таблица blocks и связанные) | Метаданные (slug, name, тип), поля, табы, секции, пресеты, связи с actions и библиотеками |
Файловая система (storage/cms/blocks/<slug>/) | Код: template.blade.php, style.scss, script.js |
Колонки таблицы blocks
| Поле | Назначение |
|---|---|
slug | Уникальный идентификатор (hero-banner, латиница нижнего регистра через дефис) |
name | Отображаемое название |
description | Описание |
block_type_id | FK на block_types (см. ниже) |
source | database / file / vendor — где живёт код блока |
path | Путь к коду (для source = file) |
controller | Кастомный PHP-контроллер (опционально) |
tags | Теги для группировки в админке |
screen | FK на files (скриншот блока для UI) |
order | Порядок в списке |
no_wrapper | Boolean — отключить автоматическую обёртку рендера |
Связанные таблицы
| Таблица | Содержит |
|---|---|
block_fields | Поля блока (см. Поля) |
block_tabs | Вкладки админ-формы блока |
block_sections | Секции внутри табов |
block_actions | Привязки actions к блоку с параметрами |
block_library | Pivot блок ↔ библиотека (внешние JS/CSS) |
block_presets | Пресеты значений полей |
page_blocks | Размещение блока на странице |
city_page_blocks | City-вариант размещения |
Файлы на диске
В директории storage/cms/blocks/<slug>/ обычно лежат:
storage/cms/blocks/hero-banner/
├── template.blade.php — Blade-шаблон рендера (обязательно)
├── style.scss — стили блока (опционально)
└── script.js — JS-логика (опционально)Типы блоков
Сидеры CMS создают четыре системных типа:
block_type_id | Тип |
|---|---|
| 1 | Контент |
| 2 | Медиа |
| 3 | Навигация |
| 4 | Формы |
Дополнительные типы создаются через UI «Типы блоков» или MCP-tool create_block_type. Тип используется для фильтрации в админке и группировки; логика рендера от типа не зависит.
Источники кода блока
Поле source в таблице blocks указывает, откуда брать файлы блока. BlockRegistry поддерживает три источника:
source | Где ищется код | Кто туда пишет |
|---|---|---|
database | storage/cms/blocks/<slug>/ | Сама CMS (правка через редактор кода в админке) |
file | app/Blocks/<slug>/ или произвольный path из БД | Разработчик вручную |
vendor | Регистрация через ServiceProvider пакета | Поставлено CMS-пакетом или модулем |
BlockRegistry::find() возвращает реализацию с высшим приоритетом источника: app > storage > vendor. Если в app/Blocks/<slug>/ лежит блок с тем же слагом — он перекроет storage и vendor.
TIP
Для блоков, которые должны попадать в Git, кладите файлы в app/Blocks/<slug>/ и установите source = file в записи блока. Для блоков, которые правят контент-менеджеры в админке, оставляйте source = database (тогда CMS сама пишет в storage/cms/blocks/).
Рендеринг блока
Рендером занимается Templite\Cms\Services\BlockRenderer. Алгоритм:
- Находит путь к блоку через
BlockRegistry::find($block->slug). - Читает
template.blade.phpиз этой директории. - Валидирует шаблон через
BladeSecurityValidator— запрещённые конструкции (прямой доступ к файловой системе, опасные функции и т.п.) приводят к отказу в рендере и записи в security-log. - Рендерит Blade с пятью переменными.
- Оборачивает результат в
<div>, если у блока не выставленno_wrapper.
Переменные в шаблоне
| Переменная | Содержимое |
|---|---|
$fields | Значения полей блока, обёрнутые в FieldsBag |
$actions | Привязанные actions блока |
$page | Eloquent-модель текущей страницы |
$global | Значения глобальных настроек |
$block | Eloquent-модель самого блока |
FieldsBag — обёртка над массивом полей. Для несуществующего ключа возвращает не null, а пустой FieldsBag. Это значит, что @foreach ($fields['missing'] as $item) пройдёт 0 итераций вместо ошибки.
Минимальный шаблон блока:
<section>
<h2>{{ $fields['title'] }}</h2>
<p>{{ $fields['description'] }}</p>
</section>Автоматическая обёртка
По умолчанию рендер каждого блока оборачивается в <div> с классами и data-атрибутами:
<div class="cms-block cms-block--hero-banner" data-block="hero-banner" data-block-id="hero-banner-65a3f...">
... содержимое блока ...
</div>Это нужно для live-preview (сопоставление DOM-элемента с блоком в админке) и для целевого CSS. Если обёртка мешает — поставьте no_wrapper = true в записи блока.
Размещение блока на странице
Связь блок ↔ страница хранится в таблице page_blocks. Колонки:
| Поле | Назначение |
|---|---|
page_id, block_id | FK |
order | Порядок на странице |
status | Опубликован / скрыт / черновик |
cache_enabled | Boolean — кэшировать рендер этого экземпляра (по умолчанию true) |
page_block_data_id | FK на page_block_data с конкретными значениями полей |
| Поля пресета | Привязанный пресет (опционально) |
Для городских вариантов используется отдельная таблица city_page_blocks с теми же полями.
Пресеты блоков
Пресет — готовый набор значений полей блока. Например, «Hero — синий» и «Hero — тёмный с видео» для одного и того же блока hero-banner.
При добавлении блока на страницу можно выбрать пресет — его значения подставляются в новый экземпляр. После этого значения можно править индивидуально, не затрагивая сам пресет.
Управление пресетами:
- UI: меню Пресеты блоков, или вкладка «Пресеты» внутри страницы блока.
- MCP: tools
list_presets,create_preset,update_preset,delete_preset.
Хранение: таблица block_presets (метаданные) + block_preset_data (значения полей пресета).
Кэширование рендера
Кэширование результата рендера каждого экземпляра блока на странице управляется флагом cache_enabled в page_blocks (по умолчанию true). Кэш инвалидируется при сохранении блока, страницы или связанных глобальных настроек.
Очистка вручную:
docker exec templite-app php artisan cms:cache-clearПересборка скомпилированных ассетов страницы (CSS/JS из блоков):
docker exec templite-app php artisan cms:compile-assetsБиблиотеки и actions
К блоку можно привязать:
- Внешние библиотеки (Swiper, AOS) через pivot-таблицу
block_library. См. Компоненты и библиотеки. - Actions (PHP-классы для обработки событий — отправка формы, click-handler) через
block_actions. Каждая привязка хранит JSON-параметры. См. Actions.
Импорт и экспорт
Блоки экспортируются в ZIP-архив через раздел Экспорт/Импорт в админке. Архив содержит:
- JSON-описание блока: метаданные, иерархия табов → секций → полей, привязанные actions и библиотеки, screenshot.
- Файлы кода блока:
template.blade.php,style.scss,script.js(если есть).
При импорте Block::fromImportArray() восстанавливает запись и связанные сущности по слагам (block_type, actions, libraries — резолвятся через ImportContext). Файлы кода кладутся обратно в storage/cms/blocks/<slug>/.
Подводные камни
Подводные камни
- Slug блока — латиница нижнего регистра через дефис (
hero-banner). Имена файлов вstorage/cms/blocks/нормализуются черезbasename($slug)(без слешей, безопасно). - Файлы блока живут в
storage/cms/blocks/<slug>/— это частьstorage/, неapp/. Обязательно включайте папку в бэкап. - Правка файлов блока в IDE снаружи CMS подхватывается автоматически, но шаблон проходит через
BladeSecurityValidatorпри каждом рендере. Если ваш шаблон содержит конструкции, которые CMS считает небезопасными, рендер вернёт HTML-комментарий вместо содержимого, а нарушение залогируется. - SCSS блока компилируется через
scssphp(PHP-реализация Sass). Не все возможности Dart Sass поддерживаются — избегайте@use ... withс keyword arguments и сложных мета-функций. После правки SCSS —cms:compile-assetsилиcms:cache-clear. - Иерархия полей (вкладки → секции → поля) хранится в БД через polymorphic-связь (
fieldable_type/fieldable_id), потому что та же иерархия используется для шаблонов страниц, типов страниц и других сущностей.
Связанные разделы
- Поля — справочник типов и доступ к значениям
- Шаблоны — где блоки рендерятся
- Страницы — где блоки размещаются
- Компоненты и библиотеки — встроенные
<x-cms::*>и внешние библиотеки - Actions — обработка событий блоков