قوالب Blade

من موسوعة حسوب
< Laravel
مراجعة 13:25، 3 أغسطس 2018 بواسطة نشد-تيسير (نقاش | مساهمات) (أنشأ الصفحة ب'<noinclude>{{DISPLAYTITLE:قوالب Blade }}</noinclude> مقدمة يقدم Laravel محرّك قولبةٍ بسيطاً لكن قويٌّ و فعّال هو Blade....')
(فرق) → مراجعة أقدم | المراجعة الحالية (فرق) | مراجعة أحدث ← (فرق)
اذهب إلى التنقل اذهب إلى البحث


مقدمة

يقدم Laravel محرّك قولبةٍ بسيطاً لكن قويٌّ و فعّال هو Blade. على خلاف محرّكات PHP أخرى، لا يمنع Blade المستخدم من استعمال شيفرات PHP في الواجهة، بل إنّه يحوِِّل صفحات Blade إلى شيفرة PHP ويخزِّنها تخزينًا مؤقتًا إلى حين تغييرها. ممّا يعني أنّ Blade لا يتطلب أيّ جهد أو وقت إضافي من التطبيق. تنتهي صفحات Blade بالامتداد blade.php. و توجد عادة في مجلد resources/views.

توريث القوالب

تعريف التخطيط

إنّ من الفوائد الأساسية لاستخدام Blade هي توريث القوالب (template inheritance) واستخدام الأقسام (sections). في البداية، سنأخذ مثالًا بسيطًا لصفحة master رئيسية. ولمّا كانت معظم تطبيقات الويب تحافظ على تخطيط عام في مختلف الصفحات، فإنَّ من الملائم تعريف هذا التخطيط العامّ في واجهة Blade:

<html>

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

</html> يمكنك الملاحظة أنّ الكود يحتوي على عناصر HTML التقليدية، لكنّه يحتوي أيضًا على التعليمتين ‎@section و ‎@yield. تُعرِّف التعليمة ‎@section قسمًا أو جزءًا لإضافة المحتوى، بينما تعرض التعليمة ‎@yield محتوى قسم معيّن. أمّا الآن بعد أن عرّفنا تخطيطًا عامًّا للتطبيق، فسنصنع الصفحات التي سترث هذا التخطيط.

تمديد التخطيط

عند إنشاء واجهة ابن جديدة، تُستخدَم التعليمة ‎@extends لتحديد أي التخطيطات يجب على هذه الواجهة أن ترث. بإمكان الواجهات التي ترث تخطيطًا أن تضيف محتوى لأحد أقسامه باستخدام تعليمات ‎@section. كما رأينا سابقًا، يمكن إظهار هذا المحتوى باستخدام التعليمة ‎@yield.

@extends('layouts.app')

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

@section('sidebar')

   @parent

يُضاف هذا للقائمة الرئيسية الجانبية.

@endsection

@section('content')

This is my body content.

@endsection في المثال السابق، يستخدم القسم sidebar التعليمة ‎@parent ليمدد (بدل إعادة تعريف) محتوى القسم في التخطيط. ستُعوَّض التعليمة ‎@parent بمحتواها من التخطيط عند استدعاء الواجهة.

ملاحظة: على عكس المثال الأول، انتهى القسم sidebar هنا بالتعليمة ‎@endsection بدل ‎@show. تُستعمَل التعليمة @‎endsection للإعلان عن انتهاء قسمٍ ما، بينما تُستعمل ‎@show لإعلان انتهاء قسم وإظهاره مباشرة.

بالإمكان إعادة واجهات Blade مباشرة من صفحة المسارات وذلك باستخدام التابع المساعد العام ‎.show Route::get('blade', function () {

   return view('child');

}); المكونات والأماكن (Components & Slots)

تُقدِم المكونات و الأماكن فوائد مشابهة لتلك التي تُقدمها الأقسام والتخطيطات و قد يجدها البعض أسهل في الفهم. في البداية. سنبدأ بصناعة مكون قابل لإعادة الاستخدام "alert" لاستخدامه في كامل التطبيق:

سوف يتضمّن المتغيّر قالب:slot$ المحتوى الذي نريد إضافته إلى المكوّن. أمّا لصناعة المكوّن، يمكن استخدام الموجّه component@:

@component('alert')

   Whoops! Something went wrong!@endcomponent

في بعض الأحيان، من المفيد تعريف عدّة أماكن (solts) لمكوّن واحد. لنقم على سبيل المثال بتغيير 'alert' التي أنشأناها لتسمح بإضافة 'title'. تُظهَر الأماكن المعنونة عن طريق استعمال متغيّرات تحمل نفس الأسماء:

@component('alert')

   @slot('title')
       Forbidden
   @endslot
   You are not allowed to access this resource!

@endcomponent تمرير بيانات إضافية للمكونات

قد نحتاج في بعض الأحيان إلى تمرير بيانات إضافية لأحدى المكوّنات، ولهذا بالإمكان تمرير مصفوفة معلومات كمعامل ثاني للتعليمة ‎@component. كل المعلومات المُمَرّرة ستكون متاحة لقالب المكوّن على شكل متغيّرات:

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

   ...

@endcomponent

أسماء بديلة للمكوّن

إن كانت المكوّنات محفوظة في ملف داخلي، بالإمكان إعطاؤها أسماءً بديلةً لتسهيل استخدامها. على سبيل المثال، إن كان المكوّن موجودًا في resources/views/components/alert.blade.php فسيكون بالإمكان استخدام التابع component لإعطاء إسم بديل للمكون components.alert ليصبح 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

إظهار البيانات يمكن إظهار البيانات المُمرّرة إلى الواجهة عن طريق إحاطة المتغيّرة بأقواس معقوفة. على سبيل المثال، لدينا المسار التالي: Route::get('greeting', function () {

   return view('welcome', ['name' => 'Samantha']);

}); يُعرَض محتوى المتغيّر name كما يلي: Hello, قالب:$name. بالطبع لستَ محدودًا بإظهار محتوى المتغيّرات المُمرّرة للواجهة، بل يمكن أيًضا إظهار نتائج دوال PHP، بل يمكن وضع أي كود PHP: The current UNIX timestamp is قالب:time(). ملاحظة: ستُمرَّر محتويات الأقواس المعقوفة {{ }} تلقائيًا إلى دالة PHP htmlspecialchars للحد من هجمات XSS. عرض البيانات غير المهرّبة في العادة، ستُمرَّر بيانات الأقواس المعقّفة إلى الدالة htmlspecialchars للحد من هجمات XSS. إن أردت أن تكون البيانات مهربةً (escaped) ، فيمكن استعمال التركيب التالي: Hello, {!! $name !!}. كن حذرًا عند عرض بيانات مقدّمة من المستخدم! استخدم دائمًا البيانات المُهرَّبة بين أقواس معقوفة للحد من الهجمات.

عرض صيغة JSON

في بعض الأحيان، قد نمرّر مصفوفة بيانات بُغية عرضها على هيئة صيغة JSON لتعريف متغير JavaScript. على سبيل المثال: <script>

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

</script> لكن عوض استخدام الدالة json_encode، يمكن استخدام التعليمة ‎@json: <script>

   var app = @json($array);

</script> ترميز كائن HTML

في الحالة العاديّة، blade [والمساعد e بصفة أخص] يرمِّز كائنات HTML بصفة مضاعفة. إن أردت إيقاف الترميز المضاعف يمكنك استدعاء التابع 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 مع إطارات JavaScript لمّا كانت العديد من إطارات JavaScript تستعمل الأقواس المعقوفة للتعبير على أن جملة معيّنة يجب أن تظهر في المتصفح، يمكن استخدام الرمز @ لإعلام محرّك الإظهار في Blade بأن الجملة يجب أن تبقى كما هي دون تغيير

Laravel

Hello, @قالب:name. في هذا المثال، سيحذف blade الرمز @ لكنه سيبقي على الجملة قالب:name كما هي ممّا سيسمح لها بأن تُعالَج في إطار JavaScript الذي تستخدمه.

التعليمة ‎@verbatim إن كنت تعرض متغيرات JavaScript في قسم كبير من الشيفرة يمكنك إحاطة شيفرة HTML بالتعليمة ‎@verbatim حتّى لا تضطر لإسباق كل تعليمة عرض بالرمز @: @verbatim

       Hello, قالب:name.

@endverbatim

بنى التحكم

بالإضافة لتوريث القوالب وعرض البيانات يُقدّم blade اختصارات مفيدة لبنى تحكّم 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 إضافة للموجّهات الشَّرطية التي ذكرناها، يُوفّر Blade التعليمتين ‎@isset و‎@empty كاختصارين لنظيريهما من دوال PHP: @isset($records)

  // $records is defined and is not null...

@endisset

@empty($records)

  // $records is "empty"...

@endempt تعليمات الاستيثاق تُستخدم التعليمات ‎@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 تعليمات الأقسام يمكن التحقّق إذا كان القسم به محتوى أم لا باستخدام التعليمة ‎@hassection: @hasSection('navigation')

       @yield('navigation')

@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)

This is user {{ $user->id }}

@endforeach

@forelse ($users as $user)

  • {{ $user->name }}
  • @empty

    No users

    @endforelse

    @while (true)

    I'm looping forever.

    @endwhile ملاحظة: عند استخدام البنى الحلقية، يمكن استخدام المتغيّرات الحلقية لكسب معلومات مهمة عن الحلقات، كمعلومات عن عدد التكرار في الحلقة.

    عند استخدام الحلقات يمكن إنهاء الحلقة أو تجاوز التكرار الجاري: @foreach ($users as $user)

       @if ($user->type == 1)
           @continue
       @endif
    
  • {{ $user->name }}
  • @if ($user->number == 5) @break @endif @endforeach يمكن إضافة عبارة شرطية مع التعليمة في نفس السطر: @foreach ($users as $user) @continue($user->type == 1)

  • {{ $user->name }}
  • @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

    This is user {{ $user->id }}

    @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 يحتوي أيضًا على عدّة خاصيات أخرى مفيدة:

    الخاصّية التعريف $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 من المفيد في بعض الأحيان تضمين كود PHP في الواجهة. يمكن استخدام الموجّه php@ لتنفيذ مقطع من كود PHP في القالب: @php

      //
    

    @endphp ملاحظة: رغم أنّ Blade يوفّر هذه الخاصّية إلّا أنّ الإكثار من استخدامها يعني أن القالب يحتوي على الكثير من التحليل المنطقي. تضمين الواجهات الفرعية

    تسمح التعليمة ‎@include بتضمين واجهة في واجهة أخرى. كل المتغيّرات المتاحة للواجهة الأم متاحة أيضًا للواجهة المضمّنة:

       @include('shared.errors')
    
       <form>
       </form>
    

    بالإضافة إلى أنها سترث كل بيانات الواجهة الأم، يمكن أيضا تمرير مصفوفة بيانات إضافية إلى الواجهة المضمّنة: @include('view.name', ['some' => 'data']) بالطبع إذا ضمّنت واجهة غير موجودة سيصدر Laravel خطأً. إذا أردت تضمين واجهة لست متأكدًا من وجودها، يمكنك استخدام التعليمة ‎@includeif: @includeWhen($boolean, 'view.name', ['some' => 'data']) لتضمين الواجهة الأولى الموجودة من مصفوفة واجهات، يمكن استخدام التعليمة ‎@includeFirst: @includeFirst(['custom.admin', 'admin'], ['some' => 'data']) تحذير: من المفضّل تجنّب استخدام الثّوابت _DIR_ و _FILE_ في الواجهات لأنها تشير إلى أماكن وجود الواجهات المترجمة والمخزّنة مؤقتًا.

    إظهار الواجهات في المجموعات بالإمكان دمج التضمين و الحلقات في سطر واحد باستخدام التعليمة ‎@each: @each('view.name', $jobs, 'job') المعامل الأول هو الواجهة الجزئية التي ستُظهَر لكل عنصر من المصفوفة أو المجموعة. المعامل الثاني هو المجموعة أو المصفوفة التي ستُكرَّر بينما المعامل الثالث هو اسم المتغيّر التي سيخصّص لحلقة التكرار الحالية في الواجهة. فعلى سبيل المثال، إن كنت تقوم بالتكرار في مصفوفة أعمال jobs، عادة ستصل إلى كل عمل عن طريق متغيّر job في الواجهة الجزئية. يكون المفتاح لحلقة التكرار الحالية متاحا في المتغيّر key من الواجهة الجزئية. يمكن أيضًا تمرير معامل رابع للتعليمة ‎@each. يحدّد هذا المعامل الواجهة التي يجب إظهارها في حال كانت المصفوفة الممرّرة فارغة: @each('view.name', $jobs, 'job', 'view.empty') ملاحظة: الواجهات المُظهَرة باستخدام التعليمة ‎@each ترث متغيّرات الواجهة الأم. إن كانت المتغيّرات إجباريةً في الواجهة اابن، فيجب استخدام الموجّه ‎@foreach و ‎@include بدًلا عن each@.

    المكادس (Stacks) يسمح Blade باستخدام مكادس (stacks) التي يمكن إظهارها في أماكن أخرى في الواجهات أو التخطيطات. يكون هذا مفيدًا في حالة تعريف مكتبة JavaScript ضرورية للواجهات الأبناء: @push('scripts')

       <script src="/example.js"></script>
    

    @endpush يمكنك الدفع إلى المكدس مرّات عديدة ثمّ لإظهار محتوى المكدس الكامل، يُمرَّر اسم المكدس كمعامل للتعليمة ‎@stack: <head>

       @stack('scripts')
    

    </head> إذا أردت إضافة محتوى لبداية المكدس، يمكن استعمال التعليمة ‎@prepend: @push('scripts')

       This will be second...
    

    @endpush

    // Later...

    @prepend('scripts')

       This will be first...
    

    @endprepend حقن الخدمات (Service Injection) تُستخدَم التعليمة ‎@inject لجلب خدمة من حاوية الخدمات. المعامل الأول المُمرَّر للتعيمة هو اسم المتغيّر التي سيحتوي الخدمة بينما المعامل الثاني هو اسم الصنف أو الواجهة للخدمة: @inject('metrics', 'App\Services\MetricsService')

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

    تمديد Blade

    يسمح Blade بتعريف تعليمات خاصّة باستعمال التابع directive. عندما يلاقي معالج Blade تعليمات خاصّة فإنّه سينجز دالة رد النداء (callback) بالتعبير الذي تحتويه التعليمة. سنُنشِئ في المثال التالي تعليمةً ‎@datetime($var)‎ التي تقبل المعامل var$ كنسخة من الصنف DateTime: <?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 بأي عبارة مُمرَّرة للتعليمة. لذا فإنّ النتيجة المُولَّدة من التعليمة هي: <?php echo ($var)->format('m/d/Y H:i'); ?> ملاحظة: بعد تغيير طريقة عمل التعليمة يجب حذف الواجهات المخزّنة مؤقتًا عن طريق أمر artisan التالي: view:clear تخصيص العبارات الشرطية تعريف موجّهات مخصّصة أكثر تعقيدًا بكثير من تعريف عبارات شرطيّة مخصّصة. لهذا يُوفّر 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 في توثيق Laravel الرسمي.