Наследование шаблонов и секции

Наследование шаблонов избавляет от дублирования: общий каркас страницы пишется один раз, а отдельные страницы лишь подставляют свой контент.

Суть: базовый макет (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-компоненты.

Проверьте себя
1. Какая пара директив связывает дочерний шаблон с макетом?
A@include и @endinclude
B@extends + @section в дочернем и @yield в макете
C@if и @endif
D@php и @endphp
2. Зачем нужна директива @include?
AПодключить переиспользуемый частичный шаблон
BОбъявить переменную
CСоздать маршрут
DЗапустить миграцию