← Заметки и статьи о Laravel PHP

10 октября 2015 перевод

Расширение условий в шаблонах Blade при помощи директив

Важными аспектами Blade являются лёгкость контроля логики и простота использования включаемых отображений (view partials). Я достаточно часто использую включаемые отображения при выводе данных в цикле, выделяя всё содержимое внутри цикла в отдельный шаблон.

Но иногда повторяются не выводимые в шаблоне данные, а логика приложения, которую сложно вынести отдельно.

Живой пример

Я пишу простое приложение на Laravel для моего тренера по фитнесу. Оно многопользовательское, и это значит, что помимо основного адреса приложения myapp.com будут ещё и дополнительные типа username.myapp.com. Для определения, в каком контексте на данный момент работает приложение (на субдомене пользователя или на главном домене), мне нужно сделать объект класса AppContext доступным глобально. В нём будет содержаться логика о контексте приложения.

Для этого я поместил в сервис-провайдере байндинг объекта класса AppContext в IOC. В этом объекте содержатся методы для определения текущего контекста приложения.

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

Это выглядело примерно так:

// random-file.blade.php
@inject('context', 'AppContext')
@if ($context->isPublic())
    // One thing
@else
    // Another thing
@endif

Это работало отлично, но выглядело не очень. Я думал о выносе переменной $isPublic или $context в каждое отображение при помощи view composer, но это всё равно чувствовалось неправильным. Я спросил у Тейлора, как быть в таких ситуациях, и он напомнил мне о кастомных директивах Blade.

Что такое директивы Blade?

Директивы позволяют вам создавать кастомные теги для Blade. В самом простом случае просто выводить кусок HTML на месте тега:

@myGreatTag
// выведет:
<a href="#">Great things here</a>

Что байндится в сервис-провайдере так:

// AppServiceProvider
    public function register()
    {
        Blade::directive('myGreatTag', function () {
            return '<a href="#">Great things here</a>';
        });
    }

... но нет смысла делать нечто подобное, так как можно использовать включаемые отображения: @include('partials.my-great-partial').

Директивы проявляют себя там, где нужно использовать для вывода не просто HTML, а HTML со смесью PHP. Например:

@if (true === true)

на самом деле преобразуется в:

<?php if(true === true): ?>

И байндинг для директивы @if выглядит так:

    protected function compileIf($expression)
    {
        return "<?php if{$expression}: ?>";
    }

Используем директивы

Очевидно, что директивы Blade позволяют нам писать шорткаты для PHP.

Это значит, что я могу переписать своё условие так:

@public
    // public thing
@else
    // non-public thing
@endif

И забайндить это так:

// AppServiceProvider
    public function register()
    {
        Blade::directive('public', function () {
            return "<?php if (app('context')->isPublic()): ?>";
        });
    }

Другие варианты

Конечно же, я мог назвать директиву @ifPublic. Или создать сеть условий. Это могли быть @ifPublic, @otherwiseBecauseYouKnowWhatTheHeck или @endIfPublicAndStuff.

Кроме того, в директивы можно посылать параметры, что добавляет уровень кастомизации:

// Bind:
Blade::directive('newlinesToBr', function($expression) {
    return "<?php echo nl2br{$expression}; ?>";
});
// Use:
<p>@newlinesToBr($body)</p>

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

Источник: https://mattstauffer.co/blog/custom-conditionals-with-laravels-blade-directives

Плюсануть
Поделиться
Отправить