Blade для PHP: полное руководство с примерами
1. Что это и зачем нужна
Blade — это мощный и элегантный шаблонизатор, входящий в состав фреймворка Laravel. Он предоставляет удобный синтаксис для работы с HTML-шаблонами, позволяя разработчикам отделять логику представления от бизнес-логики приложения. В отличие от чистого PHP, Blade предлагает лаконичные конструкции для циклов, условий, наследования шаблонов и вставки компонентов, что делает код более читаемым и поддерживаемым.
Основная задача Blade — упростить создание динамических веб-страниц. Он компилирует шаблоны в обычный PHP-код, который кэшируется до тех пор, пока шаблон не будет изменён. Это обеспечивает высокую производительность, так как на каждый запрос не требуется повторная компиляция. Blade также включает встроенную защиту от XSS-атак через экранирование вывода (функция {{ }}).
Blade идеально подходит для проектов на Laravel, но может использоваться и отдельно (через пакет jenssegers/blade). Он поддерживает наследование шаблонов (layout), секции, компоненты, слоты, условные директивы и многое другое. Благодаря своей простоте и гибкости, Blade стал стандартом де-факто для шаблонизации в экосистеме PHP.
2. Установка
Blade поставляется вместе с Laravel, поэтому для его использования в рамках фреймворка дополнительная установка не требуется. Если вы хотите использовать Blade отдельно (например, в проекте без Laravel), установите пакет через Composer:
composer require jenssegers/blade
После установки вам нужно создать экземпляр класса Blade и указать пути к шаблонам и кэшу:
use Jenssegers\Blade\Blade;
$blade = new Blade('views', 'cache');
echo $blade->render('index', ['name' => 'Мир']);
Где views — папка с шаблонами, а cache — папка для кэшированных файлов.
3. Быстрый старт — минимальный рабочий пример
Создайте файл шаблона views/hello.blade.php:
<!DOCTYPE html>
<html>
<head>
<title>Привет, {{ $name }}!</title>
</head>
<body>
<h1>Добро пожаловать, {{ $name }}!</h1>
@if (strlen($name) > 5)
<p>У вас длинное имя!</p>
@else
<p>Короткое и милое имя.</p>
@endif
</body>
</html>
Теперь создайте PHP-скрипт для рендеринга:
require 'vendor/autoload.php';
use Jenssegers\Blade\Blade;
$blade = new Blade('views', 'cache');
echo $blade->render('hello', ['name' => 'Александр']);
Результат: HTML-страница с приветствием и условным сообщением.
4. Основные методы/функции/классы
4.1. @extends — наследование шаблона
Сигнатура: @extends('layout.name')
Что делает: Указывает, что текущий шаблон наследует другой (родительский) шаблон.
Пример:
<!-- layouts/app.blade.php -->
<html>
<head>
<title>@yield('title')</title>
</head>
<body>
@yield('content')
</body>
</html>
<!-- pages/home.blade.php -->
@extends('layouts.app')
@section('title', 'Главная страница')
@section('content')
<h1>Добро пожаловать!</h1>
@endsection
4.2. @section и @yield — секции
Сигнатура: @section('name', 'default') и @yield('name', 'default')
Что делает: Определяет секцию контента, которая будет вставлена в родительский шаблон через @yield.
Пример:
<!-- parent.blade.php -->
<div>
@yield('sidebar', 'Боковая панель по умолчанию')
</div>
<!-- child.blade.php -->
@extends('parent')
@section('sidebar')
<ul>
<li>Пункт 1</li>
<li>Пункт 2</li>
</ul>
@endsection
4.3. @if, @elseif, @else — условные конструкции
Сигнатура: @if(condition) ... @elseif(condition) ... @else ... @endif
Что делает: Позволяет выполнять условный вывод HTML в зависимости от переданных данных.
Пример:
@if($score >= 90)
<p>Отлично!</p>
@elseif($score >= 60)
<p>Хорошо</p>
@else
<p>Нужно подтянуть знания</p>
@endif
4.4. @foreach — цикл по массиву
Сигнатура: @foreach($items as $item) ... @endforeach
Что делает: Итерируется по массиву или коллекции, предоставляя доступ к каждому элементу.
Пример:
<ul>
@foreach($users as $user)
<li>{{ $user->name }} ({{ $user->email }})</li>
@endforeach
</ul>
4.5. @include — включение подшаблона
Сигнатура: @include('partials.header', ['key' => 'value'])
Что делает: Включает другой шаблон в текущий, передавая ему данные.
Пример:
<!-- partials/header.blade.php -->
<header>
<h1>{{ $title ?? 'Заголовок по умолчанию' }}</h1>
</header>
<!-- main.blade.php -->
@include('partials.header', ['title' => 'Мой сайт'])
<p>Основной контент...</p>
4.6. @component и @slot — компоненты
Сигнатура: @component('alert', ['type' => 'danger']) ... @endcomponent
Что делает: Позволяет создавать переиспользуемые компоненты с именованными слотами.
Пример:
<!-- components/alert.blade.php -->
<div class="alert alert-{{ $type }}">
{{ $slot }}
@if(isset($dismiss))
<button>×</button>
@endif
</div>
<!-- Использование -->
@component('components.alert', ['type' => 'success'])
@slot('dismiss')
true
@endslot
Операция выполнена успешно!
@endcomponent
4.7. @php — выполнение произвольного PHP
Сигнатура: @php ... @endphp
Что делает: Позволяет вставить блок произвольного PHP-кода прямо в шаблон.
Пример:
@php
$now = new DateTime();
$formatted = $now->format('Y-m-d H:i:s');
@endphp
<p>Текущее время: {{ $formatted }}</p>
4.8. @csrf — защита от CSRF
Сигнатура: @csrf
Что делает: Генерирует скрытое поле с CSRF-токеном для защиты форм.
Пример:
<form method="POST" action="/submit">
@csrf
<input type="text" name="name">
<button type="submit">Отправить</button>
</form>
4.9. @error — вывод ошибок валидации
Сигнатура: @error('field') ... @enderror
Что делает: Показывает содержимое блока, если для указанного поля есть ошибка валидации.
Пример:
<input type="text" name="email" value="{{ old('email') }}">
@error('email')
<div class="alert alert-danger">{{ $message }}</div>
@enderror
4.10. @stack и @push — стековые секции
Сигнатура: @push('scripts') ... @endpush и @stack('scripts')
Что делает: Позволяет добавлять контент в стек из разных шаблонов и выводить его в одном месте.
Пример:
<!-- layout.blade.php -->
<head>
@stack('styles')
</head>
<body>
@yield('content')
@stack('scripts')
</body>
<!-- page.blade.php -->
@extends('layout')
@push('scripts')
<script src="/js/page-specific.js"></script>
@endpush
5. Реальный практический пример (100-200 строк кода)
Создадим простой блог с использованием Blade. Структура файлов:
views/layouts/master.blade.php— основной макетviews/posts/index.blade.php— список постовviews/posts/show.blade.php— отдельный постviews/components/post-card.blade.php— компонент карточки постаindex.php— точка входа
views/layouts/master.blade.php
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@yield('title', 'Мой блог')</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
@stack('styles')
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container">
<a class="navbar-brand" href="/">Блог</a>
</div>
</nav>
<main class="container mt-4">
@yield('content')
</main>
<footer class="bg-light text-center py-3 mt-5">
<p>© 2025 Мой блог</p>
</footer>
@stack('scripts')
</body>
</html>
views/components/post-card.blade.php
@props(['post' => null])
<div class="card mb-3">
<div class="card-body">
<h5 class="card-title">{{ $post['title'] }}</h5>
<p class="card-text">{{ Str::limit($post['content'], 150) }}</p>
<a href="/post/{{ $post['id'] }}" class="btn btn-primary">Читать далее</a>
</div>
<div class="card-footer text-muted">
Опубликовано: {{ $post['created_at'] }}
</div>
</div>
views/posts/index.blade.php
@extends('layouts.master')
@section('title', 'Все посты')
@section('content')
<h1 class="mb-4">Последние записи</h1>
@if(count($posts) > 0)
<div class="row">
@foreach($posts as $post)
<div class="col-md-6">
<x-post-card :post="$post" />
</div>
@endforeach
</div>
@else
<div class="alert alert-info">Пока нет ни одного поста.</div>
@endif
@endsection
views/posts/show.blade.php
@extends('