تمپلت‌های Blade

مجتبی پاکزاد لاراول 5.6.29 در حال تکمیل رایگان

مقدمه

Blade موتور تمپلت‌سازی ساده و در حین حال قدرتمندی است که توسط لاراول ارائه شده است. Blade، برخلاف دیگر موتورهای تمپلت‌سازی محبوب PHP، شما را محدود به استفاده از کدهای PHP ساده در فایل‌های ویو نمی‌کند. در حقیقت، تمام ویوهای Blade به شکل کدهای PHP کامپایل می‌شوند و تا زمان تغییر، کش می‌شوند، به این معنی که Blade در اصل هیچ سرباری به اپلیکیشن شما اضافه ‌نمی‌کند. فایل‌های ویو Blade دارای اکستنشن .blade.php هستند و معمولا در دایرکتوری resources/views نگهداری می‌شوند.

اصطلاحات فنی

سربار (Overhead)، هر ترکیب اضافی یا غیرمستقیمی از زمان، مموری، پهنای باند و یا سایر ریسورس‌ها است که برای اجرای یک تسک خاص مورد نیاز است.

ارث‌بری تمپلت

اصطلاحات فنی

قبلا در اصول شی‌گرایی به مباحث وراثت و گسترش کلاس پرداخته‌ایم، اگر به شی‌گرایی مسلط نیستید، هنوز آمادگی مطالعه داکیومنت لاراول و طبعا استفاده از آن را ندارید. توصیه می‌کنیم حتما پست مذکور را مطالعه کنید.

سِکشِن (Section) به معنی بخش است و به محدوده مشخصی از متن یا کد می‌گویند.

وراثت تمپلت (template inheritance) یعنی داشتن یک ‌لی‌اوت کلی و ارث‌بری از آن، مثلا هدر و فوتر در تمامی صفحات ثابت هستند و در این فایلِ ‌لی‌اوت مشخص شده‌اند. حالا هر فایل ویو از این لی‌اوت ارث‌بری می‌کند و اگر بخواهیم تغییری در هدر بدهیم دیگر نیازی نیست کلیه فایل‌های ویو را تغییر دهیم و تنها Partial view مربوطه را تغییر می‌دهیم. یکی از مهمترین دلایل خلق این ایده، DRY است.

تعریف لی‌‌اوت (Layout)

دو مزیت اصلی استفاده از Blade، وراثت تمپلت  و سِکشِن‌ها هستند. برای شروع، بیاید یک نمونه ساده را ببینیم. ابتدا، لی‌اوتِ یک مَستر پیج را بررسی می‌کنیم. از آنجایی که اغلب اپلیکیشن‌های وب، در صفحات مختلف از یک لی‌اوت عمومی یکسان استفاده می‌کنند، بهتر است این لی‌اوت به شکل یک فایل ویو Blade جداگانه تعریف شود.

<!-- Stored in resources/views/layouts/app.blade.php -->

<html>
    <head>
        <title>App Name - @yield('title')</title>
    </head>
    <body>
        @section('sidebar')
            This is the master sidebar.
        @show

        <div class="container">
            @yield('content')
        </div>
    </body>
</html>

همانطور که مشاهده می‌کنید، این فایل شامل تگ‌های HTML است. با این حال، به دایرکتیوهای @section و @yield توجه داشته باشید. دایرکتیو @section، همانطور که از نامش مشخص است، یک بخش یا سِکشِن محتوا را تعریف می‌کند، در حالی که دایرکتیو @yield برای نمایش محتوای یک سِکشِنِ مشخص استفاده می‌شود.

حالا که یک لی‌لوت برای اپلیکیشن‌مان تعریف کردیم، بریم یک چایلد پیج تعریف کنیم که از این لی‌اوت ارث‌بری کند.

توسعه لی‌اوت

هنگامی که یک چایلد ویو تعریف کردیم، از دایرکتیو @extends استفاده می‌کنیم تا مشخص کنیم که چایلد ویو از کدام لی‌اوت باید ارث ببرد. ویوهایی که از یک لی‌اوت Blade ارث می‌برند، با استفاده از دایرکتیو @section می‌توانند محتوا را به سِکشِن‌های لی‌اوت تزریق کنند. به خاطر داشته باشید، همانطور که در مثال بالا می‌بینید، با استفاده از دایرکتیو @yield، محتوای این سِکشِن‌ها در لی‌اوت نمایش داده خواهد شد:

<!-- Stored in resources/views/child.blade.php -->

@extends('layouts.app')

@section('title', 'Page Title')

@section('sidebar')
    @parent

    <p>This is appended to the master sidebar.</p>
@endsection

@section('content')
    <p>This is my body content.</p>
@endsection

در این مثال، سِکشِن sidebar از دایرکتیو @parent برای افزودن (به جای بازنویسی) محتوا به لی‌اوت sidebar استفاده می‌کند. هنگامی که ویو رندر شد، دایرکتیو @parent محتوای لی‌اوت را جایگزین می‌کند.

برخلاف مثال قبل، این سِکشِنِ sidebar به جای @show با @endsection پایان می‌یابد. دایرکتیو @endsection تنها یک سِکشِن تعریف می‌کند، در حالی که دایرکتیو @show بلافاصله سِکشِن را تعریف و yield میکند.

با استفاده از هلپر گلوبال view، می‌توان ویوهای blade را از داخل مسیرها برگرداند.

Route::get('blade', function () {
    return view('child');
});

کامپوننت‌ها و اسلات‌ها

کامپوننت‌ها و اسلات‌‌ها مزایایی مشابهی را برای سکشن‌ها و لی‌اوت‌ها ارائه می‌دهند؛ گرچه، احتمالا برخی از دولوپرها، مدل ذهنی کامپوننت‌ها و اسلات‌ها را ساده‌تر درک می‌کنند. ابتدا، بیایید یک کامپوننت alert با امکان استفاده مجدد را در نظر بگیریم، که می‌خواهیم چندین بار در تمام اپلیکیشن از آن استفاده کنیم.

<!-- /resources/views/alert.blade.php -->

<div class="alert alert-danger">
    {{ $slot }}
</div>

متغییر {{ $slot }} حاوی محتوایی خواهد بود که می‌خواهیم به کامپوننت‌مان تزریق کنیم. اکنون، برای ساختن این کامپوننت، می‌توانیم از دستور @component در فایل‌های استفاده کنیم:

@component('alert')
    <strong>Whoops!</strong> Something went wrong!
@endcomponent

گاهی‌اوقات، تعریف چندین اسلات برای یک کامپوننت مفید است. بیایید کامپوننت alert خود را اصلاح کنیم تا امکان اینجکت کردن یک "عنوان" را داشته باشیم. اسلات‌های نامگذاری شده می‌توانند با echo کردن متغییرهایی که با نام‌شان مطابقت دارند، نمایش داده شوند.

<!-- /resources/views/alert.blade.php -->

<div class="alert alert-danger">
    <div class="alert-title">{{ $title }}</div>

    {{ $slot }}
</div>

اکنون، با استفاده از دایرکتیو @slot می‌توانیم محتوا را در اسلات نامگذاری شده اینجکت کنیم. هر محتوایی که در دایرکتیو @slot نباشد، به کامپوننت موجود در متغییر $slot ارسال خواهد شد.

@component('alert')
    @slot('title')
        Forbidden
    @endslot

    You are not allowed to access this resource!
@endcomponent

ارسال داده‌های اضافه به کامپوننت‌ها

گاهی اوقات، ممکن است نیاز به ارسال داده‌های اضافی به یک کامپوننت داشته باشید. به همین دلیل، می‌توانید آرایه‌ای حاوی داده‌ها را به عنوان آرگومان دوم به دایرکتیو @component ارسال کنید. با اینکار تمامی داده‌ها به شکل متغییر در تمپلت کامپوننت در دسترس خواهد بود.

@component('alert', ['foo' => 'bar'])
    ...
@endcomponent

انتخاب نام مستعار برای کامپوننت‌ها

اگر کامپوننت‌های Blade شما در یک ساب‌دایرکتوری قرار دارند، جهت دسترسی آسان‌تر به آن‌ها، می‌توانید برای آن‌ها نام مستعار بگذارید. برای مثال، یک کامپوننت Blade را در نظر بگیرید که در resources/views/components/alert.blade.php قرار دارد. از متد component برای تنظیم نام مستعارِ alert برای کامپوننتِ components.alert استفاده کنید. معمولا، اینکار در متد boot از AppServiceProvider انجام می‌شود.

use Illuminate\Support\Facades\Blade;

Blade::component('components.alert', 'alert');

هنگامی که برای کامپوننت، نام مستعار قرار دهید، با استفاده از یک دایرکتیو می‌توانید آن را استفاده کنید:

@alert(['type' => 'danger'])
    You are not allowed to access this resource!
@endalert

اگر هیچ اسلات اضافه‌ای نداشته باشید، می‌توانید پارامترهای کامپوننت را حذف کنید:

@alert
    You are not allowed to access this resource!
@endalert

نمایش داده‌ها

برای نمایش داده‌های ارسال شده به ویوهای Blade، می‌توانید آن‌ها را در آکولاد قرار دهید. برای مثال، با توجه به مسیر زیر:

Route::get('greeting', function () {
    return view('welcome', ['name' => 'Samantha']);
});

محتوای متغییر $name را به صورت زیر می‌توانید نشان دهید:

Hello, {{ $name }}.

البته، محدودیتی برای نمایش محتوای متغییرهای ارسال شده به ویو ندارید. همچنین، نتایج هر فانکشن PHP را که تمایل داشته باشید، می‌توانید echo کنید. در واقع، هر کد PHP را که تمایل داشته باشید، می‌توانید در دستور اِکوی Blade قرار دهید:

The current UNIX timestamp is {{ time() }}.

دستور {{ }} در Blade برای جلوگیری از حملات XSS، به صورت خودکار قبل از اِکو کردن داده‌ها، آن‌ها را از فانکشن htmlspecialchars عبور می‌دهد.

نمایش داده‌ها بدون Escape کردن

به صورت پیش‌فرض، دستور {{ }} در Blade، برای جلوگیری از حملات XSS، داده‌ها را قبل از نمایش به فانکشن htmlspecialchars ارسال می‌کند. اگر نمی‌خواهید داده‌ها escape شوند، می‌توانید از سینتکس زیر استفاده کنید:
Hello, {!! $name !!}.

هنگامی که محتوای ارسال شده توسط کاربر را نمایش می‌دهد، خیلی دقت کنید. برای جلوگیری از حملات XSS، همیشه با استفاده از سینتکس آکولاد، داده‌های ارائه شده توسط کاربر را escape کنید.

رندر کردن JSON

گاهی ممکن است یک آرایه را با هدف رندر آن به صورت JSON به ویو ارسال کنید تا یک متغییر جاوااسکریپت را مقداردهی کنید. برای مثال:
<script>
    var app = <?php echo json_encode($array); ?>;
</script>

گرچه، به جای اینکه به صورت دستی json_encode را فراخوانی کنید، می‌توانید از دایرکتیو @json در Blade استفاده کنید:

<script>
    var app = @json($array);
</script>

HTML Entity Encoding

به صورت پیش‌فرض، Blade (و هلپر e لاراول) HTML entitiyها را دوبار اِنکود می‌کند. اگر مایلید که این دوبار اِنکود کردن را غیرفعال کنید، متد Blade::withoutDoubleEncoding را داخل متد boot کلاس AppServiceProvider فراخوانی کنید:

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Blade::withoutDoubleEncoding();
    }
}

Blade و فریمورک‌های جاوااسکریپت

از آنجایی که تعداد زیادی از فریمورک‌های جاوااسکریپت نیز از آکولاد برای نمایش یک expression معین که لازم است در مرورگر نمایش داده شود، استفاده می‌کنند، با استفاده از نماد @ می‌توانید به موتور رندر Blade بگویید که یک expression باید دست نخورده باقی بماند. برای مثال:

<h1>Laravel</h1>

Hello, @{{ name }}.

در این مثال، نماد توسط Blade حذف خواهد شد؛ با این حال، اِکسپرشن {{ name }} بدون تغییری توسط موتور Blade، دست نخورده خواهد ماند، که اجازه می‌دهد تا این expression توسط فریمورک جاوااسکریپتی شما رندر شود.

دایرکتیو @verbatim

اگر متغییرهای جاوااسکریپتی را در بخش بزرگی از تمپلت خود نمایش می‌دهید، می‌توانید کدهای HTML خود را در دایرکتیو @verbatim قرار دهید تا مجبور نباشید که به هر دستور اِکوی Blade، پیشوند @ را اضافه کنید:

@verbatim
    <div class="container">
        Hello, {{ name }}.
    </div>
@endverbatim

کنترل ساختارها

Blade علاوه بر وراثت تمپلت‌ها و نمایش داده‌ها، میانبرهای مناسبی نیز برای ساختارهای کنترلی مشترک PHP از جمله دستورات شرطی و حلقه‌ها ارائه نموده است. این میانبرها، روشی کوتاه و خیلی تمیز برای کار با ساختارهای کنترلی PHP ارائه می‌دهند، ضمن اینکه، با معادل‌های آن‌ها در PHP نیز آشنایی دارید.

دستورات If

دستورات if را با استفاده از دایرکتیوهای @if و @elseif و @else و @endif می‌توانید بسازید. این دایرکتوها مشابه معادل‌های PHP خود عمل می‌کنند.

@if (count($records) === 1)
    I have one record!
@elseif (count($records) > 1)
    I have multiple records!
@else
    I don't have any records!
@endif

Blade دایرکتیو @unless را نیز جهت راحتی ارائه کرده است:

@unless (Auth::check())
    You are not signed in.
@endunless

علاوه بر دایرکتیوهای شرطی که قبلا مطرح شد، دایرکتیوهای @isset و @empty می‌تواند به عنوان میانبرهایی مناسب برای فانکشن‌های PHP مربوطه استفاده شوند.

@isset($records)
    // $records is defined and is not null...
@endisset

@empty($records)
    // $records is "empty"...
@endempty

دایرکتیوهای اعتبارسنجی

دایرکتیوهای @auth و @guest می‌توانند برای بررسی سریع اینکه کاربر جاری احراز هویت شده است یا مهمان، استفاده شود:

@auth
    // The user is authenticated...
@endauth

@guest
    // The user is not authenticated...
@endguest

در صورت نیاز، می‌توانید یک گارد احراز هویت (authentication guard) تعیین کنید که هنگامی که از دایرکتیوهای @auth و @guest استفاده می‌شود، باید چک شود.

@auth('admin')
    // The user is authenticated...
@endauth

@guest('admin')
    // The user is not authenticated...
@endguest

دایرکتیوهای Section

با استفاده از دایرکتیو @hasSection،می‌توانید بررسی کنید که آیا یک سِکشِن محتوایی دارد یا خیر.

@hasSection('navigation')
    <div class="pull-right">
        @yield('navigation')
    </div>

    <div class="clearfix"></div>
@endif

دستورات Switch

دستورات Switch با استفاده از دایرکتیوهای @switch و @case و @break و @default و @endswitch می‌توانند ساخته شوند.

@switch($i)
    @case(1)
        First case...
        @break

    @case(2)
        Second case...
        @break

    @default
        Default case...
@endswitch

حلقه‌ها

Blade علاوه بر دستورات شرطی، دایرکتیوهای ساده‌ای را برای کار با ساختار حلقهِ PHP ارائه می‌دهد. دوباره تاکید می‌کنیم، هر کدام از این دایرکتیوها دقیقا مشابه معادل‌های PHP خود کار می‌کنند:

@for ($i = 0; $i < 10; $i++)
    The current value is {{ $i }}
@endfor

@foreach ($users as $user)
    <p>This is user {{ $user->id }}</p>
@endforeach

@forelse ($users as $user)
    <li>{{ $user->name }}</li>
@empty
    <p>No users</p>
@endforelse

@while (true)
    <p>I'm looping forever.</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

متغییر Loop

هنگامی که حلقه می‌زنید، داخل حلقه به متغییر $loop دسترسی خواهید داشت. این متغییر دسترسی به برخی اطلاعات مفید مانند ایندکس حلقه جاری و اینکه آیا این دور تکرار حلقه اولین دور است یا آخرین دور، را داخل حلقه ارائه می‌دهد:

@foreach ($users as $user)
    @if ($loop->first)
        This is the first iteration.
    @endif

    @if ($loop->last)
        This is the last iteration.
    @endif

    <p>This is user {{ $user->id }}</p>
@endforeach

اگر در حلقه‌ای با ساختار تودرتو هستید، با استفاده از پراپرتی parent، می‌توانید به متغییر $loop حلقه والد دسترسی داشته باشید:

@foreach ($users as $user)
    @foreach ($user->posts as $post)
        @if ($loop->parent->first)
            This is first iteration of the parent loop.
        @endif
    @endforeach
@endforeach

متغییر $loop، پراپرتی‌های مفید گوناگون دیگری نیز دارد:

اصطلاحات فنی

ایتِرِشِن (Iteration) که به آن پیمایش و تکرار نیز می‌گویند را در پست مباحث پیشرفته در شی‌گرایی توضیح داده‌ایم، در واقع، ایتریشن تکرار عملی به منظور تولید دنباله‌ای از خروجی‌ها است. هر تکرار یک پروسه را یک Iteration می‌گویند و پایان هر Iteration نقطه شروع Iteration بعدی است. هر جا به این اصطلاح برخورد کردید، می‌توانید به جای آن، نوبت تکرار، دور و کلمات مشابه قرار دهید تا جمله را بهتر متوجه شوید. مثلا ایتریشن جاری 3 است، یعنی سومین دور تکرار حلقه است.

پراپرتی توضیح
$loop->index اندیس ایتریشن جاری حلقه (شروع از 0).
$loop->iteration ایتریشن حلقه جاری (شروع از 1).
$loop->remaining تعداد ایتریشن‌های باقی‌مانده حلقه.
$loop->count تعداد کل آیتم‌های ایتریت شده.
$loop->first آیا این دور، اولین ایتریشن حلقه است.
$loop->last آیا این دور، آخرین ایتریشن حلقه است.
$loop->depth در ساختارهای تودرتو، سطح حلقه جاری را مشخص می‌کند.
$loop->parent هنگامی که در حلقه‌هایی تودرتو هستید، به متغییر loop حلقه والد دسترسی خواهید داشت.

کامنت‌ها

Blade امکان تعریف کامنت در ویوها را نیز ارائه می‌دهد. با این حال، برخلاف کامنت‌های HTML، کامنت‌های Blade در HTML بازگشتی توسط اپلیکیشن وجود نخواهند داشت.

{{-- This comment will not be present in the rendered HTML --}}

PHP

در بعضی شرایط، اِمبِد (embed) کردن کدهای PHP به ویوها کاربردی و مفید است. با استفاده از دایرکتیو @php، می‌توانید یک بلاک کد PHP را درون تمپلت خود اجرا کنید.

@php
    //
@endphp

Blade این فیچر را ارائه می‌کند، اما استفاده مکرر از آن، می‌تواند نشانه‌ای از این باشد که بیش از حد، لاجیک در تمپلت خود اِمبِد کرده‌اید.

اینکلود کردن ساب‌ویوها

دایرکتیو @include به شما امکان اینکلود کردن یک ویوی Blade را از داخل ویوی دیگری می‌دهد. تمامی متغییرهایی که در دسترس ویو والد هستند، در دسترس ویوی اینکلود شده نیز قرار خواهند گرفت:

<div>
    @include('shared.errors')

    <form>
        <!-- Form Contents -->
    </form>
</div>

ویوی اینکلود شده، تمامی داده‌های در دسترس در ویوی والد خود را به ارث می‌برد، با این حال، می‌توانید از طریق یک آرایه، داده‌های اضافی به ویوی اینکلود شده ارسال کنید:

@include('view.name', ['some' => 'data'])

البته، اگر سعی کنید با دایرکتیو @include ویویی که وجود ندارد را اینکلود کنید، لاراول یک خطا تولید می‌کند. اگر می‌خواهید ویویی را اینکلود کنید که وجود آن کاملا مطمئن نیستید، باید از دایرکتیو @includeIf استفاده کنید:

@includeIf('view.name', ['some' => 'data'])

اگر می‌خواهید یک ویو را بر اساس یک دستور شرطی که خروجی بولین دارد اینکلود کنید، می‌توانید از دایرکتیو @includeWhen استفاده کنید:

@includeWhen($boolean, 'view.name', ['some' => 'data'])

برای اینکلود کردن اولین ویوی موجود از بین ویوهای قرار گرفته در یک آرایه مشخص، می‌توانید از دایرکتیو includeFirst استفاده کنید:

@includeFirst(['custom.admin', 'admin'], ['some' => 'data'])

از آنجایی که ثابت‌های __DIR__ و __FILE__ به محل ویوی کامپایل و کش شده اشاره دارند، نباید از آن‌ها در ویوهای Blade استفاده کنید.

رندر کردن ویوها برای کالکشن‌ها

با دایرکتیو @each می‌توانید حلقه‌ها را ترکیب کرده و در یک خط اینکلود کنید:

@each('view.name', $jobs, 'job')

اولین آرگومان، پارشال ویو است که برای رندر کردن هر المان آرایه یا کالکشن استفاده می‌شود. دومین آرگومان، آرایه یا کالکشنی است که می‌خواهید ایتریشن را بر روی آن انجام دهید، در حالی که سومین آرگومان، نام متغییری است که داخل ویو به ایتریشن جاری تخصیص می‌یابد. بنابراین، برای مثال، اگر بر روی آرایه‌ای با نام jobs ایتریشن کنید، معمولا می‌خواهید که داخل پارشال ویو به هر شغل تحت یک متغییر با نام job دسترسی داشته باشید. کلید ایتریشن جاری نیز تحت متغییر key داخل پارشال ویو در دسترس خواهد بود.

آرگومان چهارمی را نیز می‌توانید به دایرکتیو @each ارسال کنید. این آرگومان مشخص می‌کند که در صورت خالی (empty) بودن آرایه مشخص شده، چه ویویی رندر شود.

@each('view.name', $jobs, 'job', 'view.empty')

ویوهای رندر شده به وسیله ، متغییرهای ویوی والد خود را به ارث نمی‌برند. اگر در چایلد ویو به این متغییرها نیاز دارید، باید به جای دایرکتیو @each، از @foreach و @include استفاده کنید.

استک‌ها

Blade امکان قرار دادن یک داده بر روی استک‌های نامگذاری شده (push to named stacks) را نیز ارائه می‌دهد که می‌توانند در هر جایی در ویو یا لی‌اوت دیگری رندر شوند. این ویژگی مخصوصا برای مشخص کردن لایبرری‌های جاوااسکریپت مورد نیاز چایلد ویوها بسیار کاربردی است:

@push('scripts')
    
@endpush

هر تعداد که بخواهید می‌توانید داده در استک قرار دهید. برای رندر کردن محتوای کامل استک، نام استک را به دایرکتیو @stack بدهید:

<head>
    <!-- Head Contents -->

    @stack('scripts')
</head>

اگر می‌خواهید محتوایی را به ابتدای یک استک اضافه کنید، باید از دایرکتیو @prepend استفاده کنید:

@push('scripts')
    This will be second...
@endpush

// Later...

@prepend('scripts')
    This will be first...
@endprepend

سرور اینجکشن

دایرکتیو @inject می‌تواند برای دریافت یک سرویس از سرویس کانتینر لاراول استفاده شود. اولین آرگومانی که @inject به ارسال می‌شود، نام متغییری است که سرویس در آن قرار می‌گیرد، در حالی که دومین آرگومان، نام کلاس یا اینترفیسی است که می‌خواهید توسط سرویس مورد نظرتان، resolve شود.

@inject('metrics', 'App\Services\MetricsService')

<div>
    Monthly Revenue: {{ $metrics->monthlyRevenue() }}.
</div>

توسعه دادن Blade

Blade امکان تعریف دایرکتیوهای سفارشی را با استفاده از متد directive می‌دهد. هنگامی که کامپایلر Blade با دایرکتیوهای سفارشی مواجه شود، کال‌بَکِ ارائه شده را به همراه expression موجود در دایرکتیو فراخوانی می‌کند.

مثال زیر یک دایرکتیوِ @datetime($var) می‌سازد که $var را که متغییر مشخصی است و باید نمونه‌ای (instance) از باشد را به فرمت مناسبی تبدیل می‌کند.

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Perform post-registration booting of services.
     *
     * @return void
     */
    public function boot()
    {
        Blade::directive('datetime', function ($expression) {
            return "<?php echo ($expression)->format('m/d/Y H:i'); ?>";
        });
    }

    /**
     * Register bindings in the container.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

همانطوری که مشاهده می‌کنید، متد format را به expression ارسالی به این دایرکتیو زنجیر (chain) کرده‌ایم. بنابراین، در این مثال، کد PHP نهایی تولید شده توسط این دایرکتیو، به صورت زیر خواهد بود:

<?php echo ($var)->format('m/d/Y H:i'); ?>

پس از آپدیت کردن لاجیکِ یک دایرکتیو Blade، باید تمامی ویوهای Blade کش شده را پاک کنید. ویوهای Blade کش شده را با استفاده از کامند آرتیسان view:clear می‌توانید پاک کنید.

کاستومایز کردن دستورات if

گاهی اوقات، وقتی دستورات شرطی سفارشیِ ساده تعریف می‌کنیم، برنامه‌نویسیِ یک دایرکتیوِ سفارشی پیچیده‌تر از چیزی است که نیاز داریم. به همین دلیل، Blade متد Blade::if را ارائه کرده است که امکان تعریف سریع دایرکتیوهای شرطی با استفاده از کلوژرها را ارائه می‌دهد. برای مثال، بیایید یک دستور شرطیِ سفارشی تعریف کنیم که محیط جاری اپلیکیشن را چک می‌کند. این‌کار را می‌توانیم در متد boot از AppServiceProvider انجام دهیم:

use Illuminate\Support\Facades\Blade;

/**
 * Perform post-registration booting of services.
 *
 * @return void
 */
public function boot()
{
    Blade::if('env', function ($environment) {
        return app()->environment($environment);
    });
}

هنگامی که شرط سفارشی را تعریف کردیم، به راحتی می‌توانیم در تمپلت‌های خود از آن استفاده کنیم:

@env('local')
    // The application is in the local environment...
@elseenv('testing')
    // The application is in the testing environment...
@else
    // The application is not in the local or testing environment...
@endenv
منبع
Blade Templates