Наследование шаблонов и секции
Наследование шаблонов избавляет от дублирования: общий каркас страницы пишется один раз, а отдельные страницы лишь подставляют свой контент.
Суть: базовый макет (layout) задаёт шапку, подвал и «дырки» через
@yield, а дочерние шаблоны через@extendsи@sectionзаполняют эти дырки.
Почти у каждой страницы сайта одинаковая шапка, меню и подвал. Копировать этот код в каждый шаблон — путь к катастрофе: поменяете меню в одном месте, забудете в десяти других. Наследование шаблонов решает проблему. Вы создаёте один мастер-макет с общими элементами и «дырками» для уникального контента, а каждая страница лишь заполняет эти дырки.
В Blade для этого есть пары директив. Макет объявляет точку вставки через @yield('content'), а дочерний шаблон говорит @extends('layouts.app') и заполняет точку через @section('content') ... @endsection.
Базовый макет
{{-- resources/views/layouts/app.blade.php --}}
<!DOCTYPE html>
<html lang="ru">
<head>
<title>@yield('title', 'Мой магазин')</title>
</head>
<body>
<header>Шапка и меню сайта</header>
<main>
@yield('content') {{-- сюда вставится контент страницы --}}
</main>
<footer>Подвал сайта</footer>
</body>
</html>Дочерняя страница
{{-- resources/views/products/index.blade.php --}}
@extends('layouts.app')
@section('title', 'Каталог товаров')
@section('content')
<h1>Наши товары</h1>
@foreach ($products as $product)
<p>{{ $product->name }}</p>
@endforeach
@endsectionКак работает под капотом
Когда контроллер возвращает view('products.index'), Blade видит @extends и понимает: нужно взять макет layouts.app и вставить в его @yield содержимое одноимённых секций. Результат — единая страница, собранная из каркаса и контента.
layouts/app.blade.php products/index.blade.php
-------------------- ------------------------
<header>...</header> @section('content')
<main> <---- <h1>Товары</h1>
@yield('content') <====== ...
</main> @endsection
<footer>...</footer>
|
v
Готовая страница = каркас + вставленный контent
Помимо наследования, есть директива @include для подключения переиспользуемых кусков (например, карточки товара или формы поиска):
{{-- вставить частичный шаблон и передать в него данные --}}
@include('partials.product-card', ['product' => $product])Смоделируем сборку страницы из макета и контента на Python.
Попробуй сам ▶
# Наследование шаблонов: layout с дыркой @yield
layout = (
'<header>Шапка</header>\n'
'<main>{{yield:content}}</main>\n'
'<footer>Подвал</footer>'
)
def extend(layout, sections):
page = layout
for name, content in sections.items():
page = page.replace('{{yield:' + name + '}}', content)
return page
page = extend(layout, {'content': '<h1>Каталог товаров</h1>'})
print(page)
Частые ошибки
- Имена секций не совпадают.
@yield('content')и@section('body')не свяжутся — имена должны быть идентичны. - Забыть
@endsection. Незакрытая секция ломает компиляцию шаблона. - Дублировать макет. Если копируете шапку в каждый файл — значит, наследование не используется.
Best practices
- Держите макеты в папке
layouts/, а переиспользуемые куски — вpartials/или компонентах. - Задавайте значения по умолчанию:
@yield('title', 'Сайт'). - Для современных проектов предпочитайте Blade-компоненты (следующий урок) классическому
@extends.
Помимо простого @yield, у секций есть тонкость: иногда дочерний шаблон хочет не заменить содержимое родителя, а дополнить его. Для этого внутри @section используют директиву @parent — она вставляет содержимое одноимённой секции из макета, а затем добавляет своё. Это удобно, например, для блока подключаемых стилей: базовый макет задаёт общие, а конкретная страница добавляет свои, не теряя базовые. Ещё одна полезная пара — @stack и @push: макет объявляет «стек» (например, для скриптов в конце страницы), а любой дочерний шаблон или компонент может «протолкнуть» туда свой фрагмент через @push. В итоге каждая страница сама решает, какие скрипты ей нужны, а собираются они в одном месте макета. Эти инструменты превращают наследование из простой подстановки в гибкую систему сборки страниц.
Итог: наследование шаблонов устраняет дублирование вёрстки: общий каркас один, страницы лишь подставляют контент. Дальше рассмотрим более мощный инструмент — Blade-компоненты.