Шаблоны Blade в Laravel: первые шаги для новичка
Разбираем движок шаблонов Blade в Laravel 11: как вывести данные, подключить лейаут, собрать страницу из частей и не оставить дыру для XSS. Всё, что нужно для первой рабочей вёрстки.

К концу этого материала у вас будет рабочий шаблон Laravel: страница с общим каркасом (шапка, подвал), выводом данных из контроллера и подстраницами, которые наследуют этот каркас. На всё уйдёт около 30–40 минут, если проект уже развёрнут. Пишу для Laravel 11.x — синтаксис Blade в нём совпадает с 10.x, различия отмечу по ходу.
Что нужно иметь до начала
Blade — это встроенный движок шаблонов Laravel, отдельно ставить его не нужно. Проверьте, что у вас есть:
- развёрнутый проект Laravel 11.x (проверить версию:
php artisan --version); - PHP 8.2 или выше — это требование Laravel 11;
- работающий локальный сервер:
php artisan serveотдаёт страницу наhttp://127.0.0.1:8000; - доступ к папкам
resources/viewsиroutes/web.php— там вы будете работать.
Файлы шаблонов лежат в resources/views и оканчиваются на .blade.php. Именно двойное расширение говорит фреймворку прогнать файл через Blade перед отдачей в браузер.
Шаг 1. Первый шаблон и вывод данных
Создайте файл resources/views/hello.blade.php:
<h1>Привет, {{ $name }}</h1>
<p>Сегодня {{ $date }}</p>
Двойные фигурные скобки {{ }} выводят значение и автоматически экранируют его — то есть превращают < и > в безопасные символы. Это защита от XSS: если в $name прилетит <script>, он не выполнится, а покажется как текст.
Теперь свяжите шаблон с маршрутом. В routes/web.php добавьте:
use Illuminate\Support\Facades\Route;
Route::get('/hello', function () {
return view('hello', [
'name' => 'Мир',
'date' => now()->format('d.m.Y'),
]);
});
Функция view('hello', [...]) берёт файл hello.blade.php и передаёт в него массив переменных. Откройте http://127.0.0.1:8000/hello — должна появиться строка «Привет, Мир» и текущая дата. Если видите её — связка маршрут → контроллер → шаблон работает.
Экранированный и сырой вывод
Иногда нужно вывести HTML как есть — например, готовый фрагмент из редактора. Для этого есть {!! !!}:
<div>{!! $htmlContent !!}</div>
Сырой вывод через{!! !!}применяйте только к данным, которым доверяете. Пользовательский ввод сюда пускать нельзя — это прямой путь к XSS. По умолчанию используйте{{ }}, а исключение делайте осознанно.
Шаг 2. Условия и циклы
Blade заменяет PHP-теги <?php ?> короткими директивами с символом @. Условие:
@if($user)
<p>Вы вошли как {{ $user }}</p>
@else
<p>Вы не авторизованы</p>
@endif
Цикл по списку:
<ul>
@foreach($products as $product)
<li>{{ $product }}</li>
@endforeach
</ul>
Если массив может быть пустым, есть @forelse с блоком @empty — он избавляет от отдельной проверки на пустоту:
@forelse($products as $product)
<li>{{ $product }}</li>
@empty
<li>Товаров пока нет</li>
@endforelse
Внутри цикла доступна служебная переменная $loop: $loop->first, $loop->last, $loop->index. Полезно, когда нужно, например, не ставить разделитель после последнего элемента.
Шаг 3. Общий каркас страницы
Дублировать шапку и подвал в каждом файле не нужно. Соберите базовый лейаут 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/pages/home.blade.php:
@extends('layouts.app')
@section('title', 'Главная')
@section('content')
<h1>Добро пожаловать</h1>
<p>Это главная страница.</p>
@endsection
Директива @extends указывает, какой лейаут брать. Каждый @section('content') заполняет соответствующий @yield. Свяжите с маршрутом (return view('pages.home')) и откройте страницу — вы увидите шапку, ваш заголовок и подвал вместе, хотя в файле home написаны только три строки контента.
Наследование против компонентов
С Laravel 8 появился второй способ — компоненты Blade через <x-...> и слоты. Он мощнее для переиспользуемых кусков (кнопки, карточки, модалки). В Laravel 11 работают оба подхода. Для новичка проще начать с @extends/@section — механику компонентов оставьте на потом, это отдельная тема.
Шаг 4. Подключение частей через @include
Повторяющиеся куски — навигацию, форму поиска — выносят в отдельные файлы и вставляют через @include. Создайте resources/views/partials/nav.blade.php:
<nav>
<a href="/">Главная</a>
<a href="/about">О нас</a>
</nav>
И подключите в лейауте внутри <header>:
<header>
@include('partials.nav')
</header>
В @include можно передать данные вторым аргументом: @include('partials.nav', ['active' => 'home']) — тогда внутри nav.blade.php будет доступна переменная $active.
Как это устроено под капотом (одно предложение)
Blade не интерпретирует шаблон на каждый запрос: при первом обращении он компилирует .blade.php в обычный PHP и кладёт результат в storage/framework/views, дальше отдаётся уже скомпилированный файл. Поэтому синтаксис Blade ничего не стоит по производительности в сравнении с чистым PHP.
Если не получилось
- View [hello] not found. — Laravel не нашёл файл. Проверьте имя и путь:
view('pages.home')ищетresources/views/pages/home.blade.php, точка в имени = слэш в пути. - Undefined variable $name — переменную не передали из маршрута или контроллера. Убедитесь, что она есть в массиве во втором аргументе
view(). - Изменил шаблон, а браузер показывает старое. — иногда виснет скомпилированный кеш. Выполните
php artisan view:clearи обновите страницу. - HTML выводится как текст с угловыми скобками. — вы использовали
{{ }}вместо{!! !!}. Для готового HTML нужен сырой вывод, но только для доверенных данных. - Пустая белая страница. — обычно синтаксическая ошибка в Blade (незакрытый
@ifили@section). Загляните вstorage/logs/laravel.log— там будет строка с ошибкой.
Что дальше
Когда каркас, вывод и части заработали, посмотрите в сторону компонентов Blade (<x-...> и @props) — они удобнее для переиспользуемых элементов интерфейса. Отдельно стоит изучить директивы @auth, @can и @csrf: они закрывают авторизацию и защиту форм, без которых реальную страницу не собрать. Полный список директив — в официальной документации Laravel.
Репетитор 1—11 класс и ВУЗ: Математика и физика методом наведения на мысль, помощь с ДЗ.
Спросить за 8 ₽Источники: Laravel — Blade Templates (официальная документация), Laravel — Views (официальная документация)
Частые вопросы
У меня Laravel 10, а не 11 — примеры подойдут?
В чём разница между {{ }} и {!! !!}?
Изменил шаблон, но браузер показывает старую версию. Что делать?
Обязательно ли класть шаблоны в resources/views?
Что использовать для повторяющихся блоков — @include или компоненты?
Появилась ошибка View not found, хотя файл есть. В чём дело?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.