Blade Templates

اصول آموزش Laravel

تاریخ : سه شنبه 24 بهمن 1396

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


ارث بری قالب view در لاراول


تعریف یک Layout

دو مزیت اصلی استفاده از Blade، ارث بری قالب و بخش‌ها است. برای شروع کار، یک مثال ساده را در نظر می‌گیریم؛ در ابتدا، یک صفحه master را در نظر می‌گیریم. از آنجایی که اکثر برنامه‌های کاربردی وب از یک layout کلی برای صفحات مختلف استفاده می‌کنند، برای راحتی کار می‌توان این layout را به عنوان یک ویو 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 جهت نمایش محتوای یک بخش خاص استفاده می‌شود.

پس از اینکه یک layout برای برنامه ایجاد کردیم، اجازه دهید یک صفحه فرزند که از layout ارث بری می‌کند، ایجاد کنیم.


ارث بری از یک Layout در لاراول

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

<!-- 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 در layout استفاده می‌کند. زمانی که ویو نمایش داده می‌شود، دستورالعمل @parent با محتوای layout کلی جایگزین می‌شود.

برخلاف مثال قبلی، در این مثال sidebar به جای [email protected] با [email protected] به پایان می‌رسد. دستور [email protected] فقط یک بخش را تعریف می‌کند در حالی که دستور [email protected] یک بخش را تعریف کرده و بلافاصله اجرا می‌کند.

ویوهای blade می‌توانند توسط تابع کمکی view عمومی به صورت زیر از مسیرها بازگردانده شوند:

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


کامپوننت ‌ها و اسلات ‌ها در view لاراول

کامپوننت‌ها و اسلات‌ها روش‌ مناسبی برای تعریف بخش‌ها و layoutها ارائه می‌دهند؛ شاید برای برخی افراد درک ذهنی کامپوننت‌ها و اسلات‌ها ساده‌تر باشد. در ابتدا، اجازه دهید یک کامپوننت «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 را تغییر دهیم تا امکان تزریق «title» را نیز داشته باشیم. اسلات‌های نامگذاری شده ممکن است با متغیری که با نام آن مطابقت دارد نمایش داده شوند:

<!-- /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


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

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

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


Aliasing Components

If your Blade components are stored in a sub-directory, you may wish to alias them for easier access. For example, imagine a Blade component that is stored at resources/views/components/alert.blade.php. You may use the component method to alias the component from components.alert to alert. Typically, this should be done in the boot method of your AppServiceProvider:

use Illuminate\Support\Facades\Blade;

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

Once the component has been aliased, you may render it using its alias:

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

Or, if the component has no additional slots, you may use the component's name as a Blade directive:

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


نمایش داده‌ها در view لاراول

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

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

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

Hello, {{ $name }}  .

البته، کار شما تنها به نمایش محتویات متغیرهای منتقل شده به ویو محدود نمی‌شود؛ بلکه، می‌توانید نتیجه حاصل از هر تابع PHP را نیز نمایش دهید. می‌توانید هر کد PHP را که بخواهید درون یک عبارت Blade echo قرار دهید:

The current UNIX timestamp is  {{ time() }}  .
عبارت‌های {{ }} Blade، جهت جلوگیری از حملات XSS به صورت خودکار توسط تابع پی اچ پی htmlspecialchars ارسال می‌شوند.


نمایش داده های unescaped در view

به صورت پیش‌فرض، عبارت‌های {{ }} Blade، جهت جلوگیری از حملات XSS به صورت خودکار توسط تابع پی اچ پی htmlspecialchars ارسال می‌شوند. اگر نخواهید داده‌هایتان را escaped کنید، می‌توانید از سینتکس زیر استفاده کنید:

Hello, {!! $name !!}.
در هنگام بازخوانی محتوا که توسط کاربران برنامه ارائه شده‌اند، بسیار دقت کنید. جهت جلوگیری از حملات XSS هنگام نمایش داده‌های ارائه شده توسط کاربران از {{ }} استفاده کنید.


نمایش JSON

گاهی اوقات، می‌توانید یک آرایه را به ویو خود انتقال دهید تا بتوانید آن را به عنوان یک JSON ارائه دهید و به عنوان یک متغیر جاوا اسکریپت از آن استفاده کنید. برای مثال:

<script>
    var app = <?php echo json_encode($array); ?>;
</script>

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

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


HTML Entity Encoding

ddd



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 و فریم ورک های جاوا اسکریپت در لاراول

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

<h1>Laravel</h1>

Hello, @ {{ name }}  .

در این مثال، نماد @ توسط Blade حذف می‌شود؛ با این حال، عبارت {{ name }} توسط موتور Blade تفسیر نمی‌شود و این کار مستقیماً توسط فریم ورک جاوا اسکریپت انجام می‌شود.


The دستور @verbatim در Blade لاراول

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

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


استفاده از ساختارهای کنترلی در Blade لاراول

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


استفاده از عبارات If در Blade لاراول

برای ساخت عبارات if در یک ویوی Blade، می‌توانید از دستوالعمل‌های @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 مربوط به آن‌ها در یک ویوی Blade مورد استفاده قرار گیرند:

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

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


دستورالعمل‌های احراز هویت (authentication) در Blade لاراول

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

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

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

در صورت لزوم، می‌توانید مسئول احراز هویت را به عنوان پارامتر مشخص کنید که در زمان استفاده از دستورات @auth و @guest جهت تعیین اینکه کاربر از طریق مسئول احراز هویت وارد سیستم شده است، بررسی می‌شود:

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

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


استفاده از دستورالعمل‌های section در Blade لاراول

می‌توانید محتوای یک section را با استفاده از دستور @hasSection بررسی نمایید:

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

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


استفاده از عبارت‌های switch در Blade لاراول

عبارات switch می‌توانند با استفاده از دستورالعمل‌های @switch و @case و @default و @endswitch ایجاد شوند:

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

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

    @default
        Default case...
@endswitch


استفاده از دستورات حلقه‌ در Blade لاراول

علاوه بر دستورات شرطی، 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
در زمان کار با حلقه‌ها، می‌توانید از متغیر حلقه برای بدست آوردن اطلاعات مهم در مورد حلقه موردنظر استفاده کنید، اطلاعاتی مانند اینکه در اولین یا آخرین گام تکرار حلقه قرار دارید.

همچنین، هنگام استفاده از حلقه‌ها می‌توانید حلقه را پایان دهید یا گام تکرار فعلی را حفظ کنید:

@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


متغیر حلقه در Blade لاراول

هنگام استفاده از حلقه‌ها، یک متغیر $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

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

@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 خصوصیت‌های مفید دیگری را نیز شامل می‌شود که در جدول زیر لیست شده اند:

Property Description
$loop->index The index of the current loop iteration (starts at 0).
$loop->iteration The current loop iteration (starts at 1).
$loop->remaining The iteration remaining in the loop.
$loop->count The total number of items in the array being iterated.
$loop->first Whether this is the first iteration through the loop.
$loop->last Whether this is the last iteration through the loop.
$loop->depth The nesting level of the current loop.
$loop->parent When in a nested loop, the parent's loop variable.


نحوه ثبت کامنت‌ در ‌Blade لاراول

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

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


PHP استفاده از کد

در برخی موارد، لازم است که از کد PHP در ویوهای ‌Blade خود استفاده کنید. برای این کار، می‌توانید از دستورالعمل @php برای اجرای یک بلوک ساده از کد PHP در قالب ویو خود استفاده کنید:

@php
    //
@endphp
در حالی که Blade امکان استفاده از این ویژگی را فراهم کرده است ولی با این حال استفاده از این ویژگی می‌تواند نشان دهنده این باشد که شما در گنجاندن منطق در قالب ویو خود زیاده روی کرده‌اید.


sub-view نحوه استفاده از

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

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

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

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

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

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

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

اگر بخواهید یک sub-view را براساس یک عبارت شرطی بولین با دستور @include اضافه کنید، می‌توانید از دستورالعمل @includeWhen به صورت زیر استفاده کنید:

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

جهت اضافه کردن اولین ویو موجود در آرایه‌ای از ویو‌ها، می‌توانید از دستورالعمل includeFirst به صورت زیر استفاده کنید:

@includeFirst(['custom.admin', 'admin'], ['some' => 'data'])
از بکار بردن ثابت‌های __DIR__ و __FILE__ در ویوهای Blade خود اجتناب کنید، زیرا به مکان ویو کامپایل شده و کش شده اشاره می‌کنند.


رندر کردن view با مجموعه‌‌ها در Blade

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

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

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

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

@each('view.name', $jobs, 'job', 'view.empty')
ویوهای نمایش داده شده از طریق دستور [email protected] متغیرها را از ویو والد به ارث نمی‌برند. اگر ویو فرزند به این متغیرها نیاز داشته باشد، می‌توانید به جای آن از دستور [email protected] و [email protected] استفاده کنید.


پشته Stacks

‌Blade این امکان را می‌دهد تا پشته‌های نامگذاری شده را push کنید که در جایی دیگر در داخل یک ویو یا layout رندر شود. این موضوع می‌تواند جهت تعیین کتابخانه جاوا اسکریپت موردنیاز ویوهای فرزند مفید باشد.

@push('scripts')
    <script src="/example.js"></script>
@endpush

می‌توانید یک پشته موردنیاز را چندین مرتبه push کنید. برای ارائه کامل محتویات پشته، نام پشته را به دستور @stack انتقال دهید:

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

    @stack('scripts')
</head>


تزریق خدمات یا service Injection در Blade

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

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

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


گسترش دستورالعمل‌های Blade در لاراول

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

مثال زیر یک دستور @datetime($var) ایجاد می‌کند که یک متغیر $var را فرمت دهی می‌کند که باید یک نمونه از DateTime باشد:

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 "format('m/d/Y H:i'); ?>";
        });
    }

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

همانطور که مشاهده می‌کنید، ما متد format را بر روی هر عبارت به ترتیبی که در دستورالعمل قرار دارد، اعمال می‌کنیم. بنابراین، در این مثال کد PHP تولید شده توسط این دستور به این صورت خواهد بود:

format('m/d/Y H:i'); ?>
پس از بروز رسانی منطق یک دستورالعمل Blade، باید تمام ویوهای Blade کش شده را حذف کنید. می‌توانید با استفاده از دستور آرتیسان view:clear ویوهای Blade کش شده را پاک کنید.


عبارات if سفارشی در Blade

برنامه نویسی یک دستورالعمل سفارشی، پیچیده‌تر از تعیین عبارات شرطی ساده به صورت سفارشی است. به همین دلیل Blade متد Blade::if را ارائه می‌دهد که توسط آن می‌توانید به سرعت دستورات شرطی سفارشی خود را با استفاده از Closure تعریف کنید. برای مثال، اجازه دهید یک دستور شرطی سفارشی را تعریف کنیم که محیط برنامه فعلی را بررسی می‌کند. می‌توانیم این کار را در متد 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

منابع مورد مطالعه جهت جمع آوری این مطلب:
https://laravel.com/docs/5.6/blade
https://www.lydaweb.com/article/courses/laravel-5-5-tutorial/288/blade-template-لاراول-5-5

نظرات