retro3fretro3f blog

Наследование шаблонов Blade в Laravel

Два основных преимущества использования Blade — наследование шаблонов и секции. Поскольку многие веб-приложения используют один общий макет для разных страниц, удобно определить этот макет как один layout-шаблон.

В реальных проектах шаблоны состоят из частей, что упрощает процесс разработки. К примеру, представьте что существует страница проекта:

<!DOCTYPE html>
<html>
   <head>
      <title>Заголовок страницы</title>
   </head>
   <body>
      <header>
         Шапка сайта
      </header>
      <sidebar>
         Боковое меню
      </sidebar>
      <content>
         Контент сайта
      </content>
      <footer>
         Подвал сайта
      </footer>
   </body>
</html>

В таком шаблоне можно сразу выделить три части: шапку, подвал, боковое меню и контент. Из них только контентная часть “контент” (и иногда боковое меню) будет отличаться для разных страниц сайта. Шапка и подвал для большинства страниц сайта будут неизменными. Поэтому логично выделить контент и боковое меню в отдельные файлы. Делается это с помощью механизма наследования шаблонов с помощью директив @section и @yield.

Директива @section определяет участок кода, куда будет выводиться содержимое. Благодаря чему дочерняя страница, которая наследуюет макет, сможет сама выбирать что делать с содержимым области (об этом рассказывается далее с директивой @parent).

А @yield указывает на точное место, куда будет вставлена информация.

Попробуем сделать пример макета, который можно унаследовать:

<!DOCTYPE html>
<html>
   <head>
      <title>@yield('title')</title>
   </head>
   <body>
      @section('sidebar')
         Боковое меню
      @show

      <content>
         @yield('content')
      </content>
   </body>
</html>

Этот код поместим в файл resources/views/layouts/app.blade.php. И сделаем дочерний макет, который унаследует его. Для этого создадим файл resources/views/child.blade.php и внутри него первой строкой напишем директиву @extends('layouts.app'), которая указывает на наследуемый макет:

@extends('layouts.app')
@section('title', 'Заголовок страницы')

@section('sidebar')
   @parent

   <div>
      Содержание бокового меню раздела
   </div>
@show

@section('content')
   <div>
      Содержание страницы
   </div>
@show

Обратите внимание на директиву @parent. Благодаря ей можно не польностью перезаписать существующее содержание секции, а добавить к нему содержимое. То есть @parent будет заменена содержимым макета при отрисовке представления.

Подобные дочерние представления могут быть вызваны из маршрутов с помощью функции view, которой в аргумент нужно передать название представления. В нашем случае получится так:

<?php 
   Route::get('/', function () {
      return view('child');
   });
?>

Включение подшаблонов

Директива @include позволяет включить представление в другое представление. При этом все переменные из родительского становятся доступны дочернему.

<!DOCTYPE html>
<html>
   <head>
      <title>@include('title')</title>
   </head>
   <body>
      @include('view.name')

      @section('sidebar')
         Боковое меню
      @show

      <content>
         @yield('content')
      </content>
   </body>
</html>

Из родительского представления можно передать дополнительные данные в дочерний. Делается это в виде массива, который передаётся вторым аргументом директиве @include:

@include('view.name', ['key' => 'value'])

Если сделать @include представления, которого не существует, то Laravel выдаст ошибку. Чтобы этого не происходило используйте директиву @includeIf, которая тоже включает представления, но перед этим проверяет файлы на существование. Если файлов нет, то включения представления не произойдёт. Но запрос будет выполнен без ошибок.