Введение
Blade — простой, но мощный шаблонизатор, поставляемый с Laravel. В отличие от других популярных шаблонизаторов для PHP Blade не ограничивает вас в использовании чистого PHP-кода в ваших представлениях. На самом деле все представления Blade скомпилированы в чистый PHP-код и кешированы, пока в них нет изменений, а значит, Blade практически не нагружает ваше приложение. Файлы представлений Blade используют расширение .blade.php и обычно хранятся в папке resources/views.
Наследование шаблонов
Определение макета
Два основных преимущества использования Blade — наследование шаблонов и секции. Для начала давайте рассмотрим простой пример. Во-первых, изучим макет «главной» страницы. Поскольку многие веб-приложения используют один общий макет для разных страниц, удобно определить этот макет как одно представление Blade:
<!-- Хранится в resources/views/layouts/app.blade.php -->
<html>
<head>
<title>App Name - @yield('title')</title>
</head>
<body>
@section('sidebar')
Это главная боковая панель.
@show
<div class="container">
@yield('content')
</div>
</body>
</html>
Как видите, этот файл имеет типичную HTML-разметку. Но обратите внимание на директивы @section и @yield. Директива @section, как следует из её названия, определяет секцию содержимого, а директива @yield используется для отображения содержимого данной секции.
Мы определили макет для нашего приложения, давайте определим дочернюю страницу, которая унаследует макет.
Наследование макета
При определении дочернего представления используйте Blade-директиву @extends для указания макета, который должен быть «унаследован» дочерним представлением. Представления, которые наследуют макет Blade, могут внедрять содержимое в секции макета с помощью директив @section. Запомните, как видно из приведённого выше примера, содержимое этих секций будет отображено в макете при помощи @yield:
<!-- Хранится в resources/views/child.blade.php -->
@extends('layouts.app')
@section('title', 'Page Title')
@section('sidebar')
@parent
<p>Это дополнение к основной боковой панели.</p>
@endsection
@section('content')
<p>Это содержимое тела страницы.</p>
@endsection
В этом примере секция sidebar использует директиву @parent для дополнения (а не перезаписи) содержимого к боковой панели макета. Директива @parent будет заменена содержимым макета при отрисовке представления.
Blade-представления могут быть возвращены из маршрутов при помощи глобальной вспомогательной функции PHPview()
:
Route::get('blade', function () {
return view('child');
});
Отображение данных
Вы можете отобразить данные, переданные в ваши Blade-представления, обернув переменную в фигурные скобки. Например, для такого маршрута:
Route::get('greeting', function () {
return view('welcome', ['name' => 'Samantha']);
});
Вы можете отобразить содержимое переменной name вот так:
Hello, {{ $name }}.
Вы не ограничены отображением только содержимого переменных, передаваемых в представление. Вы также можете выводить результаты любых PHP-функций. На самом деле, вы можете поместить любой необходимый PHP-код в оператор вывода Blade:
The current UNIX timestamp is {{ time() }}.
Blade-оператор PHP{{ }}
автоматически отправляется через PHP-функцию PHPhtmlentities()
для предотвращения XSS-атак.
Вывод переменных после проверки на существование
Иногда вам надо вывести значение переменной, но вы не уверены, задано ли оно. То есть вы хотите сделать так:
{{ isset($name) ? $name : 'Default' }}
Вместо написания тернарного оператора Blade позволяет вам использовать такое удобное сокращение, которое будет скомпилировано в тернарный оператор, приведённый ранее:
{{ $name or 'Default' }}
Если переменная $name имеет значение, то оно будет отображено, иначе будет выведено слово Default.
По умолчанию Blade-оператор PHP{{ }}
автоматически отправляется через PHP-функцию PHPhtmlentities()
для предотвращения XSS-атак. Если вы не хотите экранировать данные, используйте такой синтаксис:
Hello, {!! $name !!}.
Будьте очень осторожны и экранируйте переменные, которые содержат ввод от пользователя. Всегда используйте экранирование синтаксисом с двойными скобками, чтобы предотвратить XSS-атаки при отображении предоставленных пользователем данных.
Как показывает практика, вместо экранирования только пользовательских переменных безопаснее экранировать весь вывод, делая исключения только в редких случаях — прим. пер.
Blade и JavaScript-фреймворки
Поскольку многие JavaScript-фреймворки тоже используют фигурные скобки для обозначения того, что данное выражение должно быть отображено в браузере, то вы можете использовать символ @, чтобы указать механизму отрисовки Blade, что выражение должно остаться нетронутым. Например:
<h1>Laravel</h1>
Hello, @{{ name }}.
В этом примере Blade удалит символ @, но выражение PHP{{ name }}
останется нетронутым, что позволит вашему JavaScript-фреймворку отрисовать его вместо Blade.
добавлено в 5.3 ()
Управляющие конструкции
В дополнение к наследованию шаблонов и отображению данных Blade предоставляет удобные сокращения для распространенных управляющих конструкций PHP, таких как условные операторы и циклы. Эти сокращения обеспечивают очень чистый и краткий способ работы с управляющими конструкциями PHP и при этом остаются очень похожими на свои PHP-прообразы.
Оператор If
Вы можете конструировать оператор PHPif
при помощи директив PHP@if
, PHP@elseif
, PHP@else
и PHP@endif
. Эти директивы работают идентично своим PHP-прообразам:
@if (count($records) === 1)
Здесь есть одна запись!
@elseif (count($records) > 1)
Здесь есть много записей!
@else
Здесь нет записей!
@endif
Для удобства Blade предоставляет и директиву PHP@unless
:
@unless (Auth::check())
Вы не вошли в систему.
@endunless
добавлено в 5.2 ()
Циклы
В дополнение к условным операторам Blade предоставляет простые директивы для работы с конструкциями циклов PHP. Данные директивы тоже идентичны их PHP-прообразам:
@for ($i = 0; $i < 10; $i++)
Текущее значение: {{ $i }}
@endfor
@foreach ($users as $user)
<p>Это пользователь {{ $user->id }}</p>
@endforeach
@forelse($users as $user)
<li>{{ $user->name }}</li>
@empty
<p>Нет пользователей</p>
@endforelse
@while (true)
<p>Это будет длиться вечно.</p>
@endwhile
При работе с циклами вы можете использовать переменную loop для получения полезной информации о цикле, например, находитесь ли вы на первой или последней итерации цикла.
При работе с циклами вы также можете закончить цикл или пропустить текущую итерацию:
@foreach ($users as $user)
@if ($user->type == 1)
@continue
@endif
<li>{{ $user->name }}</li>
@if ($user->number == 5)
@break
@endif
@endforeach
Также можно включить условие в строку объявления директивы:
@foreach ($users as $user)
@continue($user->type == 1)
<li>{{ $user->name }}</li>
@break($user->number == 5)
@endforeach
добавлено в 5.3 ()
Переменная Loop
При работе с циклами внутри цикла будет доступна переменная PHP$loop
. Эта переменная предоставляет доступ к некоторым полезным данным, например, текущий индекс цикла, или находитесь ли вы на первой или последней итерации цикла:
@foreach ($users as $user)
@if ($loop->first)
Это первая итерация.
@endif
@if ($loop->last)
Это последняя итерация.
@endif
<p>Это пользователь {{ $user->id }}</p>
@endforeach
Если вы во вложенном цикле, вы можете обратиться к переменной PHP$loop
родительского цикла через свойство PHPparent
:
@foreach ($users as $user)
@foreach ($user->posts as $post)
@if ($loop->parent->first)
Это первая итерация родительского цикла.
@endif
@endforeach
@endforeach
Переменная PHP$loop
содержит также множество других полезных свойств:
Свойство | Описание |
---|---|
$loop->index | Индекс текущей итерации цикла (начинается с 0). |
$loop->iteration | Текущая итерация цикла(начинается с 1). |
$loop->remaining | Число оставшихся итераций цикла. |
$loop->count | Общее число элементов итерируемого массива. |
$loop->first | Первая ли это итерация цикла. |
$loop->last | Последняя ли это итерация цикла. |
$loop->depth | Уровень вложенности текущего цикла. |
$loop->parent | Переменная loop родительского цикла, для вложенного цикла. |
Комментарии
Blade также позволяет вам определить комментарии в ваших представлениях. Но в отличие от HTML-комментариев, Blade-комментарии не включаются в HTML-код, возвращаемый вашим приложением:
{{-- Этого комментария не будет в итоговом HTML --}}
PHP
В некоторых случаях бывает полезно встроить PHP-код в ваши представления. Вы можете использовать Blade-директиву PHP@php
для выполнения блока чистого PHP в вашем шаблоне:
@php
//
@endphp
Несмотря на то, что в Blade есть эта возможность, её частое использование может быть сигналом того, что у вас слишком много логики, встроенной в шаблон.
Включение подшаблонов
Blade-директива @include позволяет вам включать Blade-представление в другое представление. Все переменные, доступные родительскому представлению, будут доступны и включаемому представлению:
<div>
@include('shared.errors')
<form>
<!-- Содержимое формы -->
</form>
</div>
Хотя включаемое представление унаследует все данные, доступные родительскому представлению, вы также можете передать в него массив дополнительных данных:
@include('view.name', ['some' => 'data'])
Само собой, если вы попробуете сделать PHP@include
представления, которого не существует, то Laravel выдаст ошибку. Если вы хотите включить представление, которого может не существовать, вам надо использовать директиву PHP@includeIf
:
@includeIf('view.name', ['some' => 'data'])
Вам следует избегать использования констант __DIR__ и __FILE__ в ваших Blade-представлениях, поскольку они будут ссылаться на расположение кешированных, скомпилированных представлений.
Отрисовка представлений для коллекций
Вы можете комбинировать циклы и включения в одной строке при помощи Blade-директивы @each:
@each('view.name', $jobs, 'job')
Первый аргумент — часть представления, которую надо отрисовать для каждого элемента массива или коллекции. Второй аргумент — массив или коллекция для перебора, а третий — имя переменной, которое будет назначено для текущей итерации в представлении. Например, если вы перебираете массив jobs, то скорее всего захотите обращаться к каждому элементу как к переменной job внутри вашей части представления. Ключ для текущей итерации будет доступен в виде переменной key в вашей части представления.
Вы также можете передать четвёртый аргумент в директиву @each. Этот аргумент определяет представление, которое будет отрисовано, если данный массив пуст.
@each('view.name', $jobs, 'job', 'view.empty')
Стеки
Blade позволяет использовать именованные стеки, которые могут быть отрисованы где-нибудь ещё в другом представлении или макете. Это удобно в основном для указания любых JavaScript-библиотек, требуемых для ваших дочерних представлений:
@push('scripts')
<script src="/example.js"></script>
@endpush
«Пушить» в стек можно сколько угодно раз. Для отрисовки всего содержимого стека передайте имя стека в директиву PHP@stack
:
<head>
<!-- Содержимое заголовка -->
@stack('scripts')
</head>
Внедрение сервисов
Директива @inject служит для извлечения сервиса из сервис-контейнера Laravel. Первый аргумент, передаваемый в @inject, это имя переменной, в которую будет помещён сервис. А второй аргумент — имя класса или интерфейса сервиса, который вы хотите извлечь:
@inject('metrics', 'App\Services\MetricsService')
<div>
Месячный доход: {{ $metrics->monthlyRevenue() }}.
</div>
Наследование Blade
Blade позволяет вам определять даже свои собственные директивы с помощью метода PHPdirective()
. Когда компилятор Blade встречает пользовательскую директиву, он вызывает предоставленный обратный вызов с содержащимся в директиве выражением.
Следующий пример создаёт директиву PHP@datetime($var)
, которая форматирует данный PHP$var
, который должен быть экземпляром DateTime:
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Blade;
//для версии 5.2 и ранее:
//use Blade;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Выполнение после-регистрационной загрузки сервисов.
*
* @return void
*/
public function boot()
{
Blade::directive('datetime', function ($expression) {
return "<?php echo ($expression)->format('m/d/Y H:i'); ?>";
});
}
/**
* Регистрация привязок в контейнере.
*
* @return void
*/
public function register()
{
//
}
}
Как видите, мы прицепили метод PHPformat()
к тому выражению, которое передаётся в директиву. Поэтому финальный PHP-код, сгенерированный этой директивой, будет таким:
<?php echo ($var)->format('m/d/Y H:i'); ?>
Комментарии (4)
спасибо огромное!
https://laravel.ru/docs/v5/blade#отображение-5
$name or 'Default' у меня не работает. В чем может быть проблема? Undefined variable: name
попробуйте так :
$name ?? 'Default'
А если наоборот, файл app.blade.php хранится во resources/views, а подключаемые элементы во resources/views/layouts, как тогда app.blade.php подключить в @extends?