اكتشف إطار PHP Laravel


الدرس: طرق عرض نظيفة (2/2)


الصفحة السابقة
سنواصل نهجنا في تنظيف طرق العرض التي هي في الواقع بمثابة ذريعة لاستكشاف حاوية التبعيات التي تشكل قلب Laravel . لماذا الحاويات؟ لأنه نوع من الصناديق حيث يمكنك وضع الكثير من الأشياء. قلت لك بالفعل عن حقن التبعية عندما رأينا وحدات التحكم. إنها الحاوية التي تجعل من السهل إدارة هذه الحقن. لقد استخدمنا الحاوية بالفعل لإدارة دقة التبعية. في هذا الفصل ، سأستمر في مثال وحدات الماكرو التي شوهدت في الفصل السابق ولكن الآن باستخدام فئة.

عرض جديد


أين نحن مع تنظيف كود نموذج إنشاء المقال؟ في الفصل السابق فصلناها في قسمين مع القالب ( resources/views/template_form.blade.php) :

@extends('template')

@section('contenu')
    <br>
    <div class="col-sm-offset-3 col-sm-6">
        <div class="panel panel-info">
            <div class="panel-heading">
                @yield('titre')
            </div>
            <div class="panel-body"> 
                @yield('formulaire')
            </div>
        </div>
        {!! Html::button_back() !!}
    </div>
@endsection
والشكل نفسه المكرر بفضل وحدات الماكرو ( resources/views/post/add.blade.php) :

@extends('template_form')

@section('titre')
    Ajout d'un article
@endsection

@section('formulaire')
    {!! Form::open(['route' => 'post.store']) !!}
        {!! Form::control('text', $errors, 'titre', 'Titre') !!}
        {!! Form::control('textarea', $errors, 'contenu', 'Contenu') !!}
        {!! Form::control('text', $errors, 'tags', 'Entrez les tags séparés par des virgules') !!}
        {!! Form::button_submit('Envoyer !') !!}
    {!! Form::close() !!}
@endsection
ما أقترحه الآن هو استبدال وحدات الماكرو بطرق فئة مخصصة وإضافة معالجة اللوحة. الهدف هو الاستغناء عن القالب وتحقيق هذاالعرض:

@extends('template')

@section('contenu')
    <br>
    <div class="col-sm-offset-3 col-sm-6">
        {!! Panel::
            head(
                'Ajout d\'un article'
            )
            ->body(
                Form::open(['route' => 'post.store']).
                    Form::control('text', $errors, 'titre', 'Titre').
                    Form::control('textarea', $errors, 'contenu', 'Contenu').
                    Form::control('text', $errors, 'tags', 'Entrez les tags séparés par des virgules').
                    Form::button_submit('Envoyer !').   
                Form::close()
            )
            ->type('primary')
        !!}
        {!! Html::button_back() !!}
    </div>
@endsection
من الواضح أننا لا نرى أي اختلاف في النموذج نفسه لأنه سيكون على مستوى الإشراف. من ناحية أخرى ، تظهر فئة جديدة ( Panel) مع طرق لإنشاء اللوحة.
من الواضح أن مظهر العرض يجب ألا يتغير:
framework Laravel MVC
عرض إنشاء المقال

تنظيم الكود


في الفصل السابق ، وضعنا كود الماكرو في مزود الخدمة. كانت الطريقة بسيطة وفعالة. يكون هذا الحل ممكنًا عندما لا يكون الكود مزودًا أو معقدًا للغاية ، وإلا يصبح من الضروري بسرعة توزيعه في عدة فئات أخرى.
مفهوم "الخدمة" عام بما فيه الكفاية ليشمل معظم المهام التي يتعين القيام بها في التطبيق. أقترح عليك إنشاء خدمة لإدارة هذه الميزات للعرض. سنقوم إنشاء الملفات  Services و  Html ووضع كافة التعليمات البرمجية سنحتاج لهذا الفصل. في النهاية سيكون لدينا هذا التنظيم:
framework Laravel MVC
تنظيم الملفات
دعنا ننظر الى ما يصلح كل هذا:
  • FormBuilder  : سوف تحتوي على طرق  control و button_submit اثنين بشأن شكل،
  • HtmlBuilder  : سوف يحتوي على الطريقة button_back،
  • HtmlServiceProvider  : هو مزود الخدمة الذي سيقوم بتهيئة جميع المكونات ،
  • PanelBuilder  : سوف تحتوي على طرق اللوحة ،
  • PanelFacade  : سيتم إنشاء الواجهة للوحة ، حتى نتمكن من استخدام بناء جملة مبسط.

البنائين Builders


FormBuilder و HtmlBuilder
لإنشاء هذين البنائين ، سوف نأخذ فقط رمز الكود عن طريق وضعه في فئتين منفصلتين. لذلك بالنسبة لطريقتين من النموذج سيكون لدينا الفصل  FormBuilder  :

<?php

namespace App\Services\Html;

use Collective\Html\FormBuilder as CollectiveFormbuilder;
use Request;

class FormBuilder extends CollectiveFormbuilder
{

    public function control($type, $errors, $nom, $placeholder)
    {
        $valeur = Request::old($nom) ? Request::old($nom) : null;
        $attributes = ['class' => 'form-control', 'placeholder' => $placeholder];
        return sprintf('
            
%s %s
', $errors->has($nom) ? 'has-error' : '', call_user_func_array(['Form', $type], [$nom, $valeur, $attributes]), $errors->first($nom, ':message') ); } public function button_submit($texte) { return parent::submit($texte, ['class' => 'btn btn-info pull-right']); } }
لاحظت أنني أقوم بتمديد فئة FormBuilder  للحزمة لكي نحافظ على جميع الأساليب.
وكل ما هو HTML الطبقة  HtmlBuilder   :

<?php

namespace App\Services\Html;

use Collective\Html\HtmlBuilder as CollectiveHtmlBuilder;

class HtmlBuilder extends CollectiveHtmlBuilder
{

    public function button_back()
    {
        return '<a href="javascript:history.back()" class="btn btn-primary">
                <span class="glyphicon glyphicon-circle-arrow-left"></span> Retour
            </a>';
    }       

}
هنا أيضًا ، انا أقوم بتمديد فئة الحزمة لإضافة طريقتي.
PanelBuilder
بالنسبة للوحة ، سنقوم أيضًا بإنشاء فئة ( PanelBuilder) :

<?php

namespace App\Services\Html;

class PanelBuilder
{

  protected $type;
  protected $head;
  protected $body;
  protected $foot;

  public function __construct($type = 'default', $head = null, $body = null, $foot = null) 
  {
    $this->type = $type;
    $this->head = $head;
    $this->body = $body;
    $this->foot = $foot;
  }

  public function __toString() 
  {
    $s = '
'; if ($this->head) { $s .= '
'.$this->head.'
'; } if ($this->body) { $s .= '
'.$this->body.'
'; } if ($this->foot) { $s .= ''; } $s .= "
"; return $s; } public function type($type) { $this->type = $type; return $this; } public function head($head) { $this->head = $head; return $this; } public function body($body) { $this->body = $body; return $this; } public function footer($foot) { $this->foot = $foot; return $this; } }
لقد خططت لنكون قادرين على نقل المُدخلات إما في المنشئ ، أو عن طريق أساليب مخصصة حتى نتمكن من تعميم التعليمات البرمجية.
يجب علينا أيضًا إنشاء الواجهة للفصل Panel  :

<?php

namespace App\Services\Html;
 
use Illuminate\Support\Facades\Facade;
 
class PanelFacade extends Facade
{
 
    protected static function getFacadeAccessor() { return 'panel'; }
 
}
بناء الجملة للواجهة بسيط للغاية ، نرجع فقط إلى " panel " المرجعية. سنرى قريبًا من أين تأتي هذه الإشارة وكيف يتم تسميتها.

مزود الخدمة والواجهة


في المزود ، سيتم تحديد موقع الإشراف على الإطار. هنا هو الكود:

<?php

namespace App\Services\Html;

use Illuminate\Support\ServiceProvider;

class HtmlServiceProvider extends ServiceProvider
{

    public function register()
    {
        $this->registerHtmlBuilder();
        $this->registerFormBuilder();
        $this->registerPanelBuilder();
    }

    protected function registerHtmlBuilder()
    {
        $this->app->singleton('html', function ($app) {
            return new HtmlBuilder($app['url'], $app['view']);
        });
    }

    protected function registerFormBuilder()
    {
        $this->app->singleton('form', function ($app) {
            $form = new FormBuilder($app['html'], $app['url'], $app['view'], $app['session.store']->getToken());

            return $form->setSessionStore($app['session.store']);
        });
    }

    protected function registerPanelBuilder()
    {
        $this->app->singleton('panel', function()
        {
            return new PanelBuilder;
        });
    }

}
لقد أخبرتك بالفعل أن مقدمي الخدمة يستخدمون لتسجيل الأشياء: روابط التبعية ، والأحداث ، وعناصر الاعداد. هنا نقوم بحفظ طرق النماذج و HTML . يوجد بالفعل مزود في الحزمة:
framework Laravel MVC
مزود الحزمة
ولكن لا بد لي من تحميل معظم أساليبها. 
الطريقة الأكثر أهمية لمُزوّد الخدمات هو register . عندما تتم معالجة الطلب من قِبل Laravel ، نحتاج إلى الكثير من الأشياء: تكوين الأخطاء ، وكشف البيئة ، وتعريف البرنامج الوسيط الذي يجب أن يمر به الطلب ، والتحقق من CSRF ... في مرحلة ما سنقوم أيضا مراجعة مقدمي الخدمات وتنفيذ طريقتهم register، واحدة تلو الأخرى في ترتيب تسجيلهم. ننتهز هذه الفرصة لإعلان جميع التبعيات في الحاوية.
يشبه الحاوية حقيبة التطبيقات الكبيرة التي تتيح لك تخزين كل شيء والعثور على كل شيء. على سبيل المثال مع طريقة المزود هذه:

<?php
protected function registerPanelBuilder()
{
    $this->app->singleton('panel', function()
    {
        return new PanelBuilder;
    });
}
سوف نقول للحاوية: سوف تتذكر " panel " ، وإذا كنت بحاجة إليها ، سأقول فقط " panel " وسوف ترسل لي نسخة من PanelBuilder . وبالتالي ، ستقوم الحاوية بإنشاء رابط ( singleton) بين مرجع " panel " والفئة PanelBuilder .
إذا استخدمنا singleton فذلك يعني ، اننا نريد قرارًا واحدًا ، وإلا سنستخدم bind .
لذلك سوف تفهم بشكل أفضل كود الواجهة:

<?php
class PanelFacade extends Facade
{
 
    protected static function getFacadeAccessor() { return 'panel'; }
 
}
نقول هنا أنه إذا كان لدينا واجهة ، Panel  يجب أن نذهب ونجد في الحاوية مثيل الفئة التي تتوافق مع " panel " . ولأننا حرصنا في المُزود على إنشاء رابط بين هذا المرجع واسم الفصل ، فستعمل!
الآن إذا كتبت:

<?php
Panel::head()
هنا سوف ننظر مباشرة في الحاوية للحصول على مثيل للفئة. لكنني أستطيع أن أكتبها هكذا:

<?php
App::make('panel')->head()
هذه المرة أستخدم واجهة التطبيق (وبالتالي الحاوية لأن التطبيق امتداد له) وأطلب إنشاء مثيل للفئة المشار إليها بواسطة " panel " .
يبقى فقط إبلاغ Laravel بوجود مزودنا. ويتم ذلك في config/app.php . لتثبيت الحزمة كتبنا:

<?php
Collective\Html\HtmlServiceProvider::class,
سنغير هذا الخط لنشير الآن إلى مزودنا:

<?php
App\Services\Html\HtmlServiceProvider::class,
علينا فقط ملء الواجهة للوحة:

<?php
'Panel'     => App\Services\Html\PanelFacade::class,
وكل شيء يجب أن يعمل بشكل جيد!
إذا كنت تواجه صعوبة ، خاصة إذا كان لديك خطأ في عدم وجود فئة ، فقم بما يلي:

composer dumpautoload
php artisan clear-compiled

المكونات


يسمح التطور الحديث لحزمة LaravelCollective بإنشاء مكونات. إنه تبسيط للنهج الذي يرتكز على استخدام هذا النوع من بناء الجملة:

<?php
Form::component('button_back', 'components.form.button_back', ['nom']);
يجب إدراج هذا الإعلان في طريقة التمهيد لمقدم الخدمة (حتى تكون واجهة النموذج نشطة) .
المُدخل الأول هو اسم العنصر.
المقصود المُدخل الثاني لتحديد موقع الملف الذي يحتوي على القالب ، وهنا سيكون موجودا في resources/views/components/form/button_back.
المُدخل الأخير هو مجموعة تسمح بنقل جميع القيم لإعلام العرض. يمكنك تحديد القيم الافتراضية.
لذلك يمكننا بسهولة إنشاء القالب من كل هذا ، على سبيل المثال:

    <a href="javascript:history.back()" class="btn btn-primary">
    <span class="glyphicon glyphicon-circle-arrow-left"></span> { { $nom }}
</a>
ثم يمكننا استخدامها مباشرة في طريقة عرض:

{ { Form::button_back('Retour') }}
والتي يجب أن تؤدي في النهاية إلى هذا الكود:

<a href="javascript:history.back()" class="btn btn-primary">
    <span class="glyphicon glyphicon-circle-arrow-left"></span> Retour
</a>
إنها مقاربة أخف من تلك المقترحة في هذا الفصل ولكنها تقدم مرونة وإمكانيات أقل. لذلك لديك الخيار وفقا لاحتياجاتك.

في الخلاصة


  • إن حاوية التبعية هي مفتاح تشغيل Laravel .
  • نقوم بتسجيل مكون مع مزود الخدمة.
  • نعمل على تبسيط بناء جملة الوصول إلى الفصل الدراسي بواجهة.