Laravel/controllers

من موسوعة حسوب
مراجعة 08:14، 8 أكتوبر 2018 بواسطة تسنيم-ولهازي (نقاش | مساهمات) (أنشأ الصفحة ب' == مقدّمة == بدلًا من تعريف كامل منطق معالجة طلباتك (request handling logic) على أنّها نطاقات مغلقة ‎(Closure...')
(فرق) → مراجعة أقدم | المراجعة الحالية (فرق) | مراجعة أحدث ← (فرق)

مقدّمة

بدلًا من تعريف كامل منطق معالجة طلباتك (request handling logic) على أنّها نطاقات مغلقة ‎(Closures) في ملفّات المسارات، قد ترغب في تنظيم هذا السلوك (behavior) باستخدام أصناف ووحدات التحكّم. تستطيع وحدات التحكّم جمع منطق معالجة الطلبات ذي الصلة في صنف واحد. تخزّن وحدات التحكّم في المجلّد app/Http/Controllers.

وحدات التحكّم الأساسية

تعريف وحدات التحكّم

تجد أدناه مثالًا عن وحدة تحكّم بسيطة. لاحظ أن وحدة التحكّم تُوسّع صنف وحدة التحكّم الأساسية المُحتواة في Laravel. يوفّر الصنف الأساسي عددًا من التوابع المفيدة مثل التابع middleware الذي يُستخدم لإرفاق برمجيّة وسيطة بأفعال وحدة التحكّم:

<?php

namespace App\Http\Controllers;

use App\User;
use App\Http\Controllers\Controller;

class UserController extends Controller
{
    /**
     * المستخدم المعطى profile عرض
     *
     * @param  int  $id
     * @return Response
     */
    public function show($id)
    {
        return view('user.profile', ['user' => User::findOrFail($id)]);
    }
}

يمكنك تعريف مسار لهذه الوحدة كما يلي:

Route::get('user/{id}', 'UserController@show');

والآن عندما يطابق طلب ما رابط URI المسار المُحدّد، سيُنفّذ التابع show على الصنف UserController. ستُمرّر طبعا معاملات المسار لهذا التابع.

ملاحظة: توسيع وحدات التحكّم لصنف أساسي ليس اجباريًّا. لكن في الحالة العكس، لن تتوفر لك القدرة على استخدام خاصيّات مفيدة مثل التوابع middleware، و validate، و dispatch.

وحدات التحكّم ومجالات الأسماء (Controllers & Namespaces)

من المهم جدًّا ملاحظة أننا لم نحتاج لتحديد مجال اسم وحدة التحكّم (controller namespace) الكامل عندما عرّفنا مسار وحدة التحكّم. بما أن RouteServiceProvider يُحمّل ملفّات مساراتك داخل مجموعة مسارات تحتوي على مجال الاسم، لم نحدّد إلا جزء اسم الصنف الذي يأتي بعد جزء App\Http\Controllers من مجال الاسم.

إن اخترت أن تضع وحدة تحكّمك في موضع أعمق من المُجلّد App\Http\Controllers،استخدم اسم الصنف المخصّص لمجال الاسم الجذر App\Http\Controllers. أي إن كان صنف وحدة تحكّمك كاملا هو App\Http\Controllers\Photos\AdminController، عليك أن تُسجّل المسارات المؤدّية لوحدة التحكّم كما يلي:

Route::get('foo', 'Photos\AdminController@method');

وحدات التحكّم ذات الفعل الواحد (Single Action Controllers)

في حال رغبت في تعريف وحدة تحكّم تعالج فعلًا واحدًا، تستطيع وضع تابع invoke__ وحيد عليها:

<?php

namespace App\Http\Controllers;

use App\User;
use App\Http\Controllers\Controller;

class ShowProfile extends Controller
{
    /**
     * المستخدم المعطى profile عرض     *
     * @param  int  $id
     * @return Response
     */
    public function __invoke($id)
    {
        return view('user.profile', ['user' => User::findOrFail($id)]);
    }
}

لا تحتاج لتحديد تابع عند تسجيل المسارات لوحدات التحكّم ذات الفعل الواحد:

Route::get('user/{id}', 'ShowProfile');

تستطيع توليد وحدة تحكّم قابلة للاستدعاء (invokable) باستخدام الخيار invokable-- من أمر Artisan  make:controller:

php artisan make:controller ShowProfile --invokable

برمجيّة وحدة تحكّم الوسيطة

يمكن تعيين برمجيّة وسيطة على مسارات وحدة التحكّم في ملف مساراتك:

Route::get('profile', 'UserController@show')->middleware('auth');

بالرغم من ذلك، يظل من المناسب أكثر تحديد البرمجيّات الوسيطة داخل التابع الباني ‎(constructor). تستطيع تعيين البرمجيّات الوسيطة على أفعال وحدة التحكّم بسهولة باستخدام التابع middleware من تابع وحدة التحكّم الباني ‎(constructor). يمكنك حتى حصر البرمجيّة الوسيطة لتوابع معيّنة من صنف وحدة التحكّم:

class UserController extends Controller
{
    /**
     * إنشاء نسخة وحدة تحكّم جديدة
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('auth');

        $this->middleware('log')->only('index');

        $this->middleware('subscribed')->except('store');
    }
}

تسمح لك وحدات التحكّم أيضًا بتسجيل البرمجيّات الوسيطة باستخدام نطاق مغلق ‎(Closure) طريقة ملائمة لتعريف برمجيّة وسيطة لوحدة تحكّم واحدة دون تعريف صنف برمجيّة وسيطة كامل:

$this->middleware(function ($request, $next) {
   // ...

    return $next($request);
});

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

وحدات تحكّم الموارد

يعيّن توجيه (routing) الموارد في Laravel المسارات "CRUD" المعتادة على وحدة التحكّم بسطر برمجي واحد. على سبيل المثال، قد ترغب بإنشاء وحدة تحكّم تعالج كل الطلبات HTTP للصور "photos" المخزونة بتطبيقك. نستطيع إنشاء وحدة تحكّم من هذا النوع بسرعة باستخدام أمر  make:controller Artisan:

php artisan make:controller PhotoController --resource

يُولّد هذا الأمر وحدة تحكّم في app/Http/Controllers/PhotoController.php. ستحتوي وحدة التحكّم على تابع لكل عمليّة (operation) موارد متوفّرة. قد تريد في الخطوة التالية تسجيل مسار كثير الموارد ‎(resourceful) لوحدة التحكّم:

Route::resource('photos', 'PhotoController');

يُنشئ تصريح المسار الوحيد هذا عدّة مسارات لمعالجة أفعال متنوّعة على المورد. ستحتوي وحدة التحكّم المُولّدة على بذار (stubs) توابع لكل فعل من هذه الأفعال مع ملاحظات تعلمك بطرق HTTP (بمعنى HTTP verbs) والروابط ‎(URIs) التي يعالجونها. قد تُسجّل عدّة وحدات تحكّم موارد مرّة واحدة بتمرير مصفوفة للتابع resources:

Route::resources([
    'photos' => 'PhotoController',
    'posts' => 'PostController'
]);

الطرق التي تعالجها وحدة تحكّم الموارد

Route Name Action URI Verb
photos.index index /photos GET
photos.create create /photos/create GET
photos.store store /photos POST
photos.show show /photos/{photo} GET
photos.edit edit /photos/{photo}/edit GET
photos.update update /photos/{photo} PUT/PATCH
photos.destroy destroy /photos/{photo} DELETE

تحديد نموذج المورد

إذا كنت تستخدم ارتباط نموذج المسارات وترغب في جعل توابع وحدة التحكّم تُلمّح على نسخة من النموذج، تستطيع استخدام الخيار model-- عند توليد وحدة التحكّم:

php artisan make:controller PhotoController --resource --model=Photo

انتحال توابع الاستمارات (Spoofing Form Methods)

نظرًا لأن استمارات HTML لا تقدر على تقديم طلبات PUT أو PATCH أو DELETE، ستحتاج إلى إضافة حقل method_ مخفي لانتحال طرق HTTP. يمكن للتوجيه method Blade@ إنشاء هذا الحقل لك:

<form action="/foo/bar" method="POST">
    @method('PUT')
</form>

مسارات الموارد الجزئية

يمكنك تحديد مجموعة فرعية من الأفعال (actions) التي يجب أن تُعالجها وحدة التحكّم بدلاً من معالجة المجموعة الكاملة من الأفعال الافتراضية عند التصريح بمسار مورد:

Route::resource('photos', 'PhotoController')->only([
    'index', 'show'
]);

Route::resource('photos', 'PhotoController')->except([
    'create', 'store', 'update', 'destroy'
]);

مسارات موارد الواجهة البرمجيّة

نحتاج عادة عند التصريح بمسارات الموارد التي ستستهلكها الواجهات البرمجيّة إلى  المسارات التي تقدم قوالب HTML مثل create و edit. لتسهيل العمليّة ، يمكنك استخدام التابع apiResource لاستبعاد هذين المسارين تلقائيًا:

Route::apiResource('photos', 'PhotoController');

يمكنك تسجيل العديد من وحدات تحكّم موارد الواجهة البرمجيّة  مرّة واحدة من خلال تمرير مصفوفة للتابع apiResources:

Route::apiResources([
    'photos' => 'PhotoController',
    'posts' => 'PostController'
]);

لإنشاء وحدة تحكّم مورد واجهة برمجيّة بسرعة ولا تتضمن التابعين create أو edit، استخدم المفتاح api-- (بمعنى switch) عند تنفيذ الأمر make:controller:

php artisan make:controller API/PhotoController --api

تسمية مسارات الموارد

لكل أفعال وحدة تحكّم الموارد اسم مسار افتراضيًّا. ولكن يمكنك إعادة تعريف (override) هذه الأسماء بتمرير مصفوفة names  تحتوي اختياراتك:

Route::resource('photos', 'PhotoController')->names([
    'create' => 'photos.build'
]);

تسمية معاملات مسارات الموارد

سينشئ Route::resource معاملات (parameters) المسار لمسارات مواردك استنادًا إلى الإصدار (version) "المُفرَّد" (singularized) من اسم المورد. يمكنك إعادة تعريف هذا بسهولة لكل مورد على انفراد باستخدام التابع parameters. يجب أن تكون المصفوفة المُمرّرة للتابع parameters مصفوفةً ترابطيّةً (associative array) لأسماء المصادر وأسماء المعاملات:

Route::resource('users', 'AdminUserController')->parameters([
    'users' => 'admin_user'
])

ينشئ المثال أعلاه عناوين روابط URI التالية لمسار المورد show:

/users/{admin_user}