Blade и шаблоны

Директивы, наследование шаблонов, компоненты, экранирование, формы.

Junior Что такое Blade? Как выводятся данные и в чём разница {{ }} и {!! !!}?

Blade — встроенный шаблонизатор Laravel. Шаблоны компилируются в чистый PHP и кэшируются (storage/framework/views), поэтому оверхед минимален.

{{ $name }}            {{-- вывод с экранированием через htmlspecialchars (защита от XSS) --}}
{!! $html !!}          {{-- вывод БЕЗ экранирования — только для доверенного HTML --}}
{{ $name ?? 'Гость' }} {{-- значение по умолчанию --}}
@{{ не blade }}        {{-- экранирование самой директивы --}}

Комментарии {{-- ... --}} не попадают в итоговый HTML (в отличие от <!-- -->).

Проверка: {!! !!} с пользовательскими данными — типичная XSS-уязвимость; на собеседовании об этом спросят почти наверняка.

Junior Какие основные директивы Blade вы знаете?

Условия:

@if ($users->isEmpty()) ... @elseif (...) ... @else ... @endif
@unless ($user->active) ... @endunless
@isset($var) ... @endisset
@empty($items) ... @endempty
@auth ... @endauth      @guest ... @endguest
@switch($role) @case('admin') ... @break @default ... @endswitch

Циклы:

@foreach ($posts as $post) ... @endforeach
@forelse ($posts as $post) ... @empty ... @endforelse
@for / @while

Внутри циклов доступен объект $loop: $loop->first, $loop->last, $loop->iteration, $loop->even.

Прочее:

@include('partials.nav', ['active' => 'home'])
@csrf  @method('PUT')
@php ... @endphp
@verbatim ... @endverbatim   {{-- вывод без обработки Blade (для Vue/JS) --}}

Кастомные директивы: Blade::directive('money', fn ($e) => "...").

Junior Как работает наследование шаблонов: @extends, @section, @yield?

Мастер-шаблон layouts/app.blade.php:

<html>
<head><title>@yield('title', 'По умолчанию')</title></head>
<body>
    @yield('content')
</body>
</html>

Дочерний шаблон:

@extends('layouts.app')

@section('title', 'Главная')

@section('content')
    <h1>Привет</h1>
@endsection
  • @yield('name') — место вставки секции;
  • @section('name') ... @endsection — содержимое секции;
  • @parent — вставить содержимое родительской секции;
  • @show вместо @endsection — вывести секцию сразу в родителе;
  • @push('scripts') / @stack('scripts') — именованные стеки (удобно для JS/CSS из дочерних шаблонов).
Junior Зачем в формах @csrf и @method? Что будет без них?

@csrf вставляет скрытое поле с CSRF-токеном:

<form method="POST" action="/posts">
    @csrf
</form>

HTML-формы отправляют cookies сессии, поэтому без проверки токена сайт уязвим к CSRF-атакам (чужой сайт отправляет форму от имени залогиненного пользователя). Middleware ValidateCsrfToken сверяет токен из поля _token с токеном сессии. Без @csrf — ошибка 419 Page Expired.

@method — эмуляция HTTP-глаголов, которых нет в HTML-формах (только GET/POST):

<form method="POST" action="/posts/1">
    @csrf
    @method('DELETE')
</form>

Генерирует <input type="hidden" name="_method" value="DELETE">, и Laravel маршрутизирует запрос как DELETE.

В API (SPA) вместо поля используется заголовок X-CSRF-TOKEN / Sanctum.

Middle Blade-компоненты: что это и чем отличаются от @include?

Компоненты — переиспользуемые куски UI с изоляцией данных. Два вида:

Класс + шаблон:

php artisan make:component Alert
class Alert extends Component
{
    public function __construct(public string $type = 'info') {}
    public function render() { return view('components.alert'); }
}
<x-alert type="error" :message="$errorText" />

Анонимные — только шаблон в resources/views/components/:

{{-- components/badge.blade.php --}}
@props(['color' => 'gray'])
<span class="badge-{{ $color }}">{{ $slot }}</span>

<x-badge color="red">Важно</x-badge>

Отличия от @include:

  • атрибуты и слоты ({{ $slot }}, именованные <x-slot:title>);
  • :prop передаёт выражение PHP, prop — строку;
  • слияние атрибутов: {{ $attributes->merge(['class' => 'base']) }};
  • изоляция: компонент не видит переменные родителя, пока их явно не передать.

@include проще, но «протекает» контекстом и не имеет API слотов.