Тема
Blade Templates
Структура директорий
resources/views/
├── layouts/ — layouts (app, admin, email)
├── components/ — переиспользуемые компоненты
├── pages/ — статические страницы
├── {section}/ — динамические секции (services/, brands/, etc.)
├── partials/ — фрагменты, не являющиеся компонентами
└── errors/ — 404, 500, 503Layouts
- Один основной layout:
layouts.app— header, footer, meta, Vite assets - Отдельный layout для разделов с другим дизайном (calc, email)
- Sections:
@yield('title'),@yield('description'),@yield('content'),@yield('meta') - Стек для скриптов:
@stack('scripts')в layout,@push('scripts')в page
Escaping — критично
| Синтаксис | Когда | Пример |
|---|---|---|
| ВСЕГДА по умолчанию | Имя, цена, описание |
{!! $html !!} | ТОЛЬКО доверенный HTML из админки | SEO-блоки, rich content из Filament |
@js($var) | Передача в JS | Blade → Alpine/JS переменная |
{!! !!} с пользовательским вводом = XSS уязвимость. Без исключений.
Компоненты
Anonymous vs Class-based
- Anonymous (файл в
components/) — для простых UI-блоков без логики - Class-based — когда нужна логика подготовки данных, инъекция сервисов
Props
@propsс типизацией и default-значениями- Обязательные props — без default
- Массивы/объекты:
:prop="$var"(с двоеточием)
Типичные компоненты проекта
| Компонент | Назначение |
|---|---|
| breadcrumbs | Навигация с Schema.org BreadcrumbList |
| seo-blocks | SEO-контент по position/page_type |
| contact-form | Форма заявки (CSRF, валидация) |
| cta-block | Call-to-action блок |
| pagination | Кастомная пагинация |
SEO в шаблонах
Каждая публичная страница ОБЯЗАНА содержать:
<title>через@section('title')<meta name="description">через@section('description')- Canonical URL
- Open Graph: og:title, og:description, og:url, og:type
- Breadcrumbs с Schema.org BreadcrumbList
- Structured data (JSON-LD) по типу страницы
Partials и циклы
@includeдля фрагментов, не являющихся компонентами (card в цикле)@forelseвместо@foreach— всегда обрабатывать пустое состояние (@empty)- Не использовать
@includeв глубокой вложенности (3+ уровня) — заменить на компонент
Assets (Vite)
- CSS и JS — через
@vite()directive - Не инлайнить большие CSS/JS блоки в шаблоне
- Изображения из medialibrary — через URL модели, не хардкод путей
- Lazy loading для изображений ниже fold:
loading="lazy"
Условные секции
@auth/@guest— для авторизованных/гостевых блоков@isset($var)— безопасная проверка перед использованием@env('production')— для production-only (analytics, tracking)- Не дублировать логику в Blade — если сложное условие, вычислить в контроллере/сервисе
Anti-patterns
| Паттерн | Проблема | Решение |
|---|---|---|
{!! $userInput !!} | XSS уязвимость | |
| Запросы к БД в Blade | Скрытые N+1, невозможно профилировать | Подготовить данные в контроллере |
@php блоки с логикой | Blade — не место для логики | Контроллер / Service / ViewComposer |
@foreach без @empty | Пустой список — пустая страница | @forelse + @empty |
Хардкод URL в <a href="/..."> | Ломается при смене роутов | route('name') или url() |
@include 4+ уровней вложенности | Невозможно отследить поток данных | Компонент |
| CSS/JS инлайн в шаблоне | Не кешируется, дублируется | Vite assets |
| Отсутствие canonical / og:tags | Плохой SEO, дубли в индексе | Всегда в layout |
| Автопрокрутка/marquee-анимации | Раздражают пользователя, нарушают UX | Горизонтальный overflow-x:auto + drag-to-scroll |
| Emoji вместо иконок (UI-блоки, отрасли) | Непрофессионально, нет контроля над стилем | Только SVG-иконки |