Blade-шаблоны в Laravel: на что смотреть новичку
Разбираем базовый синтаксис Blade в Laravel 11: вывод данных, наследование макетов, компоненты и частые ошибки, из-за которых шаблон не отображается или выдаёт HTML в виде текста.

К концу материала у вас будет рабочий layout, страница, которая его наследует, и переиспользуемый компонент — три кирпича, на которых держатся почти все шаблоны в Laravel. Всё написано под Laravel 11.x (актуальная версия на конец 2024 года), но синтаксис Blade в версиях 9–11 совпадает, поэтому большая часть подойдёт и для более старых проектов.
Что нужно иметь до начала
Blade — не отдельный пакет, он входит в состав фреймворка. Отдельно ставить ничего не нужно, но чтобы примеры заработали, у вас должно быть:
- установленный проект Laravel (проверьте командой
php artisan --version— она должна вывести версию 9 или выше); - запущенный сервер разработки:
php artisan serve, по умолчанию сайт откроется наhttp://127.0.0.1:8000; - минимальное понимание маршрутов — где лежит файл
routes/web.php.
Файлы шаблонов лежат в resources/views и имеют расширение .blade.php. Именно это двойное расширение говорит Laravel, что файл нужно прогнать через Blade, а не отдать как есть.
Как связать маршрут и шаблон
Blade сам по себе ничего не показывает — его вызывает контроллер или маршрут. Начнём с самого короткого пути. Откройте routes/web.php и добавьте маршрут:
// routes/web.php — Laravel 11.x
use Illuminate\Support\Facades\Route;
Route::get('/hello', function () {
// Первый аргумент — имя файла без .blade.php
// Второй — данные, которые уедут в шаблон
return view('hello', ['userName' => 'Анна']);
});
Теперь создайте файл resources/views/hello.blade.php:
<!-- resources/views/hello.blade.php -->
<h1>Привет, {{ $userName }}</h1>
Проверка: откройте http://127.0.0.1:8000/hello — в браузере появится заголовок «Привет, Анна». Если вместо имени видите {{ $userName }} текстом — файл сохранён без расширения .blade.php либо вы открыли не тот путь.
Вывод данных: две конструкции, которые путают
В Blade есть два способа вывести переменную, и разница между ними — вопрос безопасности:
{{ $value }}— экранирует HTML. Если в переменной лежит<b>текст</b>, на странице вы увидите буквально<b>текст</b>, а не жирный шрифт. Это защита от XSS, и по умолчанию нужно использовать именно её.{!! $value !!}— выводит без экранирования. Применяйте только для данных, которым доверяете: например, HTML из собственного редактора. Никогда не пропускайте через него то, что ввёл пользователь.
Правило новичка: по умолчанию всегда двойные фигурные скобки. Восклицательные — сознательное исключение, и каждое такое место вы должны уметь объяснить.
Наследование макета
Дублировать <head>, шапку и подвал на каждой странице — путь к боли. Blade решает это наследованием. Создайте макет resources/views/layouts/app.blade.php:
<!-- resources/views/layouts/app.blade.php -->
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8">
<title>@yield('title', 'Мой сайт')</title>
</head>
<body>
<header>Общая шапка</header>
<main>
@yield('content')
</main>
<footer>Общий подвал</footer>
</body>
</html>
@yield('content') — это дырка, которую заполнит конкретная страница. Второй аргумент в @yield('title', 'Мой сайт') — значение по умолчанию, если страница заголовок не задала.
Теперь страница, которая наследует макет — resources/views/about.blade.php:
<!-- resources/views/about.blade.php -->
@extends('layouts.app')
@section('title', 'О нас')
@section('content')
<h1>О компании</h1>
<p>Здесь текст только этой страницы.</p>
@endsection
Точка в layouts.app — это разделитель папок: файл лежит в resources/views/layouts/app.blade.php. Добавьте маршрут Route::get('/about', fn () => view('about')); и откройте страницу.
Проверка: вы увидите общую шапку и подвал из макета, а между ними — заголовок «О компании». Во вкладке браузера будет «О нас».
Директивы вместо PHP-скобок
Внутри Blade условия и циклы пишут через директивы с собакой, а не через <?php ?>:
@if ($orders->isEmpty())
<p>Заказов пока нет.</p>
@else
<ul>
@foreach ($orders as $order)
<li>Заказ №{{ $order->id }} — {{ $order->total }} ₽</li>
@endforeach
</ul>
@endif
Ставить собственные <?php ?> технически можно, но это признак того, что логика полезла в шаблон. Расчёты и выборки — задача контроллера, шаблон только показывает готовое.
Компоненты: переиспользуемые блоки
Когда одна и та же кнопка или карточка встречается на десяти страницах, её выносят в компонент. Начиная с Laravel 7 есть удобная команда:
# создаст класс и шаблон компонента alert
php artisan make:component Alert
Команда создаёт два файла: класс app/View/Components/Alert.php и шаблон resources/views/components/alert.blade.php. Если логика не нужна и хватает только разметки, можно сделать компонент без класса:
# --view создаст только шаблон, без PHP-класса
php artisan make:component alert --view
Вставляют компонент через тег с префиксом x-:
<x-alert type="error">
Не удалось сохранить заказ.
</x-alert>
Внутри шаблона компонента переданный атрибут type доступен как переменная, а содержимое между тегами — через {{ $slot }}. Точную настройку свойств компонента и работу со слотами смотрите в официальной документации, раздел Blade → Components — там показано, как объявлять публичные свойства класса.
Если не получилось
Пять ошибок, на которые новичок натыкается в первую неделю:
- View [hello] not found. Laravel не нашёл шаблон. Проверьте путь и расширение: файл должен называться
hello.blade.phpи лежать вresources/views. В имениview('hello')расширение не пишут. - Undefined variable $userName. Переменную не передали из маршрута или контроллера, либо опечатались в имени. Blade сам данные не придумывает — сверьте ключ в массиве
view('hello', ['userName' => ...])с именем в шаблоне. - На странице виден
{{ $userName }}текстом. Файл не прошёл через Blade — почти всегда потому, что расширение.phpвместо.blade.php. - Изменения в шаблоне не появляются. Laravel компилирует Blade в PHP и кеширует. Обычно кеш обновляется сам, но если завис — выполните
php artisan view:clear. - HTML выводится как текст, хотя должен быть разметкой. Вы использовали
{{ }}там, где данным можно доверять и нужен рендер. Осознанно замените на{!! !!}— но только убедившись, что источник безопасен.
Что делать дальше
Когда три кирпича собраны, следующий шаг — перенести логику подготовки данных в контроллер вместо замыканий в маршрутах: php artisan make:controller. После этого посмотрите на компоненты со слотами и атрибутами — они заменяют большую часть копипаста в разметке. Инвалидация и прекомпиляция шаблонов для продакшена (php artisan view:cache) — отдельная тема, здесь мы её не разворачивали.
Контент-конвейер: Из одной идеи — текст, изображение, озвучка и ролик. Один заказ вместо четырёх.
Спросить за 60 ₽Источники: Laravel Documentation — Blade Templates, Laravel Documentation — Views
Частые вопросы
У меня Laravel 9, а не 11 — примеры подойдут?
Чем @yield отличается от @section?
Когда использовать {{ }}, а когда {!! !!}?
Правки в шаблоне не появляются на странице — что делать?
Можно ли писать PHP-код прямо в Blade-шаблоне?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.