Skip to content

Blueprint: Контентные страницы (Pages)

Когда применять

Страницы, которые контент-менеджер создаёт/правит в админке: «О компании», «Доставка», «Гарантии», лендинги услуг без собственной модели.

Не применять для: страниц с собственной сущностью (услуга, товар, статья — у них свои модели и blueprint'ы), главной (обычно отдельный контроллер с виджетами).

Состав решения

  • Модель Page + миграция + фабрика
  • Контроллер PageController@show (route model binding по slug)
  • Filament-ресурс PageResource
  • Blade pages/show.blade.php на общем layout
  • Feature-тест PageTest + запись в sitemap-генерацию

Схема данных

СтолбецТипИндексCast / примечание
ididPK
titlestringH1 страницы
slugstringuniquekebab-case, [a-z0-9-]
contentlongText nullableHTML из RichEditor
blocksjson nullablecast array; если нужен блочный конструктор (Filament Builder)
meta_titlestring nullableприоритет над шаблонным
meta_descriptionstring nullable
is_activeboolean default trueindexскрытие без удаления
published_attimestamp nullableотложенная публикация (если требуется ТЗ)
timestamps

Правила реализации

  • Роут: GET /{page:slug} последним в web.php (fallback-паттерн) либо с префиксом /info/{page:slug} — решить по ТЗ; коллизии со статичными роутами проверять тестом.
  • Binding — только is_active страницы: resolveRouteBinding или explicit query в контроллере; неактивная → 404.
  • Вывод content{!! !!} допустим: HTML доверенный, из админки (по specs/blade). Пользовательского ввода в content нет.
  • SEO: title/description по приоритету «ручное поле → шаблон → default»; canonical, OG-теги в layout (specs/seo). Страницы — в sitemap (только активные).
  • Кеш: страница кешируется тегом pages; afterSave ресурса — flush тега.
  • Filament: RichEditor (или Builder при blocks), slug авто из title с unique(ignoreRecord: true), секция SEO — collapsed.
  • Блочный конструктор (blocks) вводить только если ТЗ требует разнотипные секции; для текстовых страниц достаточно RichEditor — не переусложнять.

Пакеты

Ничего специального. Медиа в контенте — стандартный аттачмент RichEditor или spatie/laravel-medialibrary при галереях.

Шаги

  1. Миграция + модель (+ scope active).
  2. Контроллер show + роут с ->name('page.show').
  3. Blade-шаблон на layout с @section('title')/@section('description').
  4. Filament-ресурс с SEO-секцией и flush кеша.
  5. Sitemap: включить активные страницы.
  6. Тесты: активная → 200 + title/h1; неактивная → 404; несуществующий slug → 404.

Чеклист приёмки

  • [ ] Неактивная страница недоступна и отсутствует в sitemap
  • [ ] Slug уникален, меняется без дублей; смена slug опубликованной страницы → предупредить о 301
  • [ ] Meta ручные приоритетнее автогенерации; canonical есть
  • [ ] Правка в админке видна на сайте сразу (кеш-теги сброшены)
  • [ ] Роут страницы не перекрывает статические роуты (тест)

Внутренняя база знаний студии