الفرق بين المراجعتين ل"Laravel/controllers"

من موسوعة حسوب
اذهب إلى التنقل اذهب إلى البحث
(أنشأ الصفحة ب' == مقدّمة == بدلًا من تعريف كامل منطق معالجة طلباتك (request handling logic) على أنّها نطاقات مغلقة ‎(Closure...')
 
 
(13 مراجعة متوسطة بواسطة مستخدمين اثنين آخرين غير معروضة)
سطر 1: سطر 1:
 
+
<noinclude>{{DISPLAYTITLE:وحدات التحكّم (Controllers) في Laravel}}</noinclude>
== مقدّمة ==
+
== مقدمة ==
بدلًا من تعريف كامل منطق معالجة طلباتك (request handling logic) على أنّها نطاقات مغلقة ‎(Closures) في ملفّات المسارات، قد ترغب في تنظيم هذا السلوك (behavior) باستخدام أصناف ووحدات التحكّم. تستطيع وحدات التحكّم جمع منطق معالجة الطلبات ذي الصلة في صنف واحد. تخزّن وحدات التحكّم في المجلّد app/Http/Controllers.
+
بدلًا من تعريف كامل منطق معالجة طلباتك (request handling logic) على أنّها نطاقات مغلقة (‎(Closures في ملفّات المسارات، قد ترغب في تنظيم هذا السلوك (behavior) باستخدام أصناف ووحدات التحكّم. تستطيع وحدات التحكّم جمع منطق معالجة الطلبات ذي الصلة في صنف واحد. تخزّن وحدات التحكّم في المجلّد <code>app/Http/Controllers</code>.
  
 
== وحدات التحكّم الأساسية ==
 
== وحدات التحكّم الأساسية ==
  
 
=== تعريف وحدات التحكّم ===
 
=== تعريف وحدات التحكّم ===
تجد أدناه مثالًا عن وحدة تحكّم بسيطة. لاحظ أن وحدة التحكّم تُوسّع صنف وحدة التحكّم الأساسية المُحتواة في Laravel. يوفّر الصنف الأساسي عددًا من التوابع المفيدة مثل التابع middleware الذي يُستخدم لإرفاق برمجيّة وسيطة بأفعال وحدة التحكّم:<syntaxhighlight lang="php">
+
تجد أدناه مثالًا عن وحدة تحكّم بسيطة. لاحظ أن وحدة التحكّم تُوسّع صنف وحدة التحكّم الأساسية المُحتواة في [[Laravel]]. يوفّر الصنف الأساسي عددًا من التوابع المفيدة مثل التابع <code>middleware</code> الذي يُستخدم لإرفاق برمجيّة وسيطة بأفعال وحدة التحكّم:<syntaxhighlight lang="php">
 
<?php
 
<?php
  
سطر 31: سطر 31:
 
Route::get('user/{id}', 'UserController@show');
 
Route::get('user/{id}', 'UserController@show');
  
</syntaxhighlight>والآن عندما يطابق طلب ما رابط URI المسار المُحدّد، سيُنفّذ التابع show على الصنف UserController. ستُمرّر طبعا معاملات المسار لهذا التابع.
+
</syntaxhighlight>والآن عندما يطابق طلب ما رابط URI المسار المُحدّد، سيُنفّذ التابع <code>show</code> على الصنف <code>UserController</code>. ستُمرّر طبعا معاملات المسار لهذا التابع.
  
ملاحظة: توسيع وحدات التحكّم لصنف أساسي ليس اجباريًّا. لكن في الحالة العكس، لن تتوفر لك القدرة على استخدام خاصيّات مفيدة مثل التوابع middleware، و validate، و dispatch.
+
ملاحظة: توسيع وحدات التحكّم لصنف أساسي ليس اجباريًّا. لكن في الحالة العكس، لن تتوفر لك القدرة على استخدام خاصيّات مفيدة مثل التوابع <code>middleware</code>، و <code>validate</code>، و <code>dispatch</code>.
  
==== وحدات التحكّم ومجالات الأسماء (Controllers & Namespaces) ====
+
=== وحدات التحكّم ومجالات الأسماء (Controllers & Namespaces) ===
من المهم جدًّا ملاحظة أننا لم نحتاج لتحديد مجال اسم وحدة التحكّم (controller namespace) الكامل عندما عرّفنا مسار وحدة التحكّم. بما أن RouteServiceProvider يُحمّل ملفّات مساراتك داخل مجموعة مسارات تحتوي على مجال الاسم، لم نحدّد إلا جزء اسم الصنف الذي يأتي بعد جزء App\Http\Controllers من مجال الاسم.
+
من المهم جدًّا ملاحظة أننا لم نحتاج لتحديد مجال اسم وحدة التحكّم (controller namespace) الكامل عندما عرّفنا مسار وحدة التحكّم. بما أن <code>RouteServiceProvider</code> يُحمّل ملفّات مساراتك داخل مجموعة مسارات تحتوي على مجال الاسم، لم نحدّد إلا جزء اسم الصنف الذي يأتي بعد جزء <code>App\Http\Controllers</code> من مجال الاسم.
إن اخترت أن تضع وحدة تحكّمك في موضع أعمق من المُجلّد App\Http\Controllers،استخدم اسم الصنف المخصّص لمجال الاسم الجذر App\Http\Controllers. أي إن كان صنف وحدة تحكّمك كاملا هو App\Http\Controllers\Photos\AdminController، عليك أن تُسجّل المسارات المؤدّية لوحدة التحكّم كما يلي:<syntaxhighlight lang="php">
+
إن اخترت أن تضع وحدة تحكّمك في موضع أعمق من المُجلّد <code>App\Http\Controllers</code>،استخدم اسم الصنف المخصّص لمجال الاسم الجذر <code>App\Http\Controllers</code>. أي إن كان صنف وحدة تحكّمك كاملا هو <code>App\Http\Controllers\Photos\AdminController</code>، عليك أن تُسجّل المسارات المؤدّية لوحدة التحكّم كما يلي:<syntaxhighlight lang="php">
 
Route::get('foo', 'Photos\AdminController@method');
 
Route::get('foo', 'Photos\AdminController@method');
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 
=== وحدات التحكّم ذات الفعل الواحد (Single Action Controllers) ===
 
=== وحدات التحكّم ذات الفعل الواحد (Single Action Controllers) ===
في حال رغبت في تعريف وحدة تحكّم تعالج فعلًا واحدًا، تستطيع وضع تابع invoke__ وحيد عليها:<syntaxhighlight lang="php">
+
في حال رغبت في تعريف وحدة تحكّم تعالج فعلًا واحدًا، تستطيع وضع تابع <code>invoke__</code> وحيد عليها:<syntaxhighlight lang="php">
 
<?php
 
<?php
  
سطر 66: سطر 66:
 
Route::get('user/{id}', 'ShowProfile');
 
Route::get('user/{id}', 'ShowProfile');
  
</syntaxhighlight>تستطيع توليد وحدة تحكّم قابلة للاستدعاء (invokable) باستخدام الخيار invokable-- من أمر Artisan  make:controller:<syntaxhighlight lang="php">
+
</syntaxhighlight>تستطيع توليد وحدة تحكّم قابلة للاستدعاء (invokable) باستخدام الخيار <code>invokable--</code> من أمر <code>Artisan  make:controller</code>:<syntaxhighlight lang="php">
 
php artisan make:controller ShowProfile --invokable
 
php artisan make:controller ShowProfile --invokable
  
سطر 74: سطر 74:
 
يمكن تعيين برمجيّة وسيطة على مسارات وحدة التحكّم في ملف مساراتك:<syntaxhighlight lang="php">
 
يمكن تعيين برمجيّة وسيطة على مسارات وحدة التحكّم في ملف مساراتك:<syntaxhighlight lang="php">
 
Route::get('profile', 'UserController@show')->middleware('auth');
 
Route::get('profile', 'UserController@show')->middleware('auth');
</syntaxhighlight>بالرغم من ذلك، يظل من المناسب أكثر تحديد البرمجيّات الوسيطة داخل التابع الباني (constructor). تستطيع تعيين البرمجيّات الوسيطة على أفعال وحدة التحكّم بسهولة باستخدام التابع middleware من تابع وحدة التحكّم الباني (constructor). يمكنك حتى حصر البرمجيّة الوسيطة لتوابع معيّنة من صنف وحدة التحكّم:<syntaxhighlight lang="php">
+
</syntaxhighlight>بالرغم من ذلك، يظل من المناسب أكثر تحديد البرمجيّات الوسيطة داخل التابع الباني (constructor). تستطيع تعيين البرمجيّات الوسيطة على أفعال وحدة التحكّم بسهولة باستخدام التابع <code>middleware</code> من تابع وحدة التحكّم الباني (constructor). يمكنك حتى حصر البرمجيّة الوسيطة لتوابع معيّنة من صنف وحدة التحكّم:<syntaxhighlight lang="php">
 
class UserController extends Controller
 
class UserController extends Controller
 
{
 
{
سطر 92: سطر 92:
 
}
 
}
  
</syntaxhighlight>تسمح لك وحدات التحكّم أيضًا بتسجيل البرمجيّات الوسيطة باستخدام نطاق مغلق (Closure) طريقة ملائمة لتعريف برمجيّة وسيطة لوحدة تحكّم واحدة دون تعريف صنف برمجيّة وسيطة كامل:<syntaxhighlight lang="php">
+
</syntaxhighlight>تسمح لك وحدات التحكّم أيضًا بتسجيل البرمجيّات الوسيطة باستخدام نطاق مغلق (Closure) طريقة ملائمة لتعريف برمجيّة وسيطة لوحدة تحكّم واحدة دون تعريف صنف برمجيّة وسيطة كامل:<syntaxhighlight lang="php">
 
$this->middleware(function ($request, $next) {
 
$this->middleware(function ($request, $next) {
 
   // ...
 
   // ...
سطر 102: سطر 102:
  
 
== وحدات تحكّم الموارد ==
 
== وحدات تحكّم الموارد ==
يعيّن توجيه (routing) الموارد في Laravel المسارات "CRUD" المعتادة على وحدة التحكّم بسطر برمجي واحد. على سبيل المثال، قد ترغب بإنشاء وحدة تحكّم تعالج كل الطلبات HTTP للصور "photos" المخزونة بتطبيقك. نستطيع إنشاء وحدة تحكّم من هذا النوع بسرعة باستخدام أمر  make:controller Artisan:<syntaxhighlight lang="php">
+
يعيّن توجيه (routing) الموارد في Laravel المسارات "CRUD" المعتادة على وحدة التحكّم بسطر برمجي واحد. على سبيل المثال، قد ترغب بإنشاء وحدة تحكّم تعالج كل الطلبات HTTP للصور "photos" المخزونة بتطبيقك. نستطيع إنشاء وحدة تحكّم من هذا النوع بسرعة باستخدام أمر  <code>make:controller Artisan</code>:<syntaxhighlight lang="php">
 
php artisan make:controller PhotoController --resource
 
php artisan make:controller PhotoController --resource
</syntaxhighlight>يُولّد هذا الأمر وحدة تحكّم في app/Http/Controllers/PhotoController.php. ستحتوي وحدة التحكّم على تابع لكل عمليّة (operation) موارد متوفّرة.
+
</syntaxhighlight>يُولّد هذا الأمر وحدة تحكّم في <code>app/Http/Controllers/PhotoController.php</code>. ستحتوي وحدة التحكّم على تابع لكل عمليّة (operation) موارد متوفّرة.
قد تريد في الخطوة التالية تسجيل مسار كثير الموارد (resourceful) لوحدة التحكّم:<syntaxhighlight lang="php">
+
قد تريد في الخطوة التالية تسجيل مسار كثير الموارد (resourceful) لوحدة التحكّم:<syntaxhighlight lang="php">
 
Route::resource('photos', 'PhotoController');
 
Route::resource('photos', 'PhotoController');
  
سطر 117: سطر 117:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
==== الطرق التي تعالجها وحدة تحكّم الموارد ====
+
=== الطرق التي تعالجها وحدة تحكّم الموارد ===
 
{| class="wikitable"
 
{| class="wikitable"
!Route Name
+
!اسم المسار
!Action
+
!الفعل
!URI
+
!العنوان URI
!Verb
+
!الطريقة
 
|-
 
|-
 
|photos.index
 
|photos.index
|index
+
|<code>index</code>
 
|<code>/photos</code>
 
|<code>/photos</code>
 
|GET
 
|GET
 
|-
 
|-
 
|photos.create
 
|photos.create
|create
+
|<code>create</code>
 
|<code>/photos/create</code>
 
|<code>/photos/create</code>
 
|GET
 
|GET
 
|-
 
|-
 
|photos.store
 
|photos.store
|store
+
|<code>store</code>
 
|<code>/photos</code>
 
|<code>/photos</code>
 
|POST
 
|POST
 
|-
 
|-
 
|photos.show
 
|photos.show
|show
+
|<code>show</code>
|<code>/photos/{photo}</code>
+
|{‎<code>/photos/{photo</code>
 
|GET
 
|GET
 
|-
 
|-
 
|photos.edit
 
|photos.edit
|edit
+
|<code>edit</code>
|<code>/photos/{photo}/edit</code>
+
|<code>/photos/{photo}/edit</code>
 
|GET
 
|GET
 
|-
 
|-
 
|photos.update
 
|photos.update
|update
+
|<code>update</code>
|<code>/photos/{photo}</code>
+
|{‎<code>/photos/{photo</code>
 
|PUT/PATCH
 
|PUT/PATCH
 
|-
 
|-
 
|photos.destroy
 
|photos.destroy
|destroy
+
|<code>destroy</code>
|<code>/photos/{photo}</code>
+
|{‎<code>/photos/{photo</code>
 
|DELETE
 
|DELETE
 
|}
 
|}
  
==== تحديد نموذج المورد ====
+
=== تحديد نموذج المورد ===
إذا كنت تستخدم ارتباط نموذج المسارات وترغب في جعل توابع وحدة التحكّم تُلمّح على نسخة من النموذج، تستطيع استخدام الخيار model-- عند توليد وحدة التحكّم:<syntaxhighlight lang="php">
+
إذا كنت تستخدم ارتباط نموذج المسارات وترغب في جعل توابع وحدة التحكّم تُلمّح على نسخة من النموذج، تستطيع استخدام الخيار <code>model--</code> عند توليد وحدة التحكّم:<syntaxhighlight lang="php">
 
php artisan make:controller PhotoController --resource --model=Photo
 
php artisan make:controller PhotoController --resource --model=Photo
  
 
</syntaxhighlight>
 
</syntaxhighlight>
  
==== انتحال توابع الاستمارات (Spoofing Form Methods) ====
+
=== انتحال توابع الاستمارات (Spoofing Form Methods) ===
نظرًا لأن استمارات HTML لا تقدر على تقديم طلبات PUT أو PATCH أو DELETE، ستحتاج إلى إضافة حقل method_ مخفي لانتحال طرق HTTP. يمكن للتوجيه method Blade@ إنشاء هذا الحقل لك:<syntaxhighlight lang="html">
+
نظرًا لأن استمارات HTML لا تقدر على تقديم طلبات PUT أو PATCH أو DELETE، ستحتاج إلى إضافة حقل <code>method_</code> مخفي لانتحال طرق HTTP. يمكن للتوجيه method Blade@ إنشاء هذا الحقل لك:<syntaxhighlight lang="html">
 
<form action="/foo/bar" method="POST">
 
<form action="/foo/bar" method="POST">
 
     @method('PUT')
 
     @method('PUT')
سطر 186: سطر 186:
  
 
==== مسارات موارد الواجهة البرمجيّة ====
 
==== مسارات موارد الواجهة البرمجيّة ====
نحتاج عادة عند التصريح بمسارات الموارد التي ستستهلكها الواجهات البرمجيّة إلى  المسارات التي تقدم قوالب HTML مثل create و edit. لتسهيل العمليّة ، يمكنك استخدام التابع apiResource لاستبعاد هذين المسارين تلقائيًا:<syntaxhighlight lang="php">
+
نحتاج عادة عند التصريح بمسارات الموارد التي ستستهلكها الواجهات البرمجيّة إلى  المسارات التي تقدم قوالب HTML مثل create و edit. لتسهيل العمليّة ، يمكنك استخدام التابع <code>apiResource</code> لاستبعاد هذين المسارين تلقائيًا:<syntaxhighlight lang="php">
 
Route::apiResource('photos', 'PhotoController');
 
Route::apiResource('photos', 'PhotoController');
  
</syntaxhighlight>يمكنك تسجيل العديد من وحدات تحكّم موارد الواجهة البرمجيّة  مرّة واحدة من خلال تمرير مصفوفة للتابع apiResources:<syntaxhighlight lang="php">
+
</syntaxhighlight>يمكنك تسجيل العديد من وحدات تحكّم موارد الواجهة البرمجيّة  مرّة واحدة من خلال تمرير مصفوفة للتابع <code>apiResources</code>:<syntaxhighlight lang="php">
 
Route::apiResources([
 
Route::apiResources([
 
     'photos' => 'PhotoController',
 
     'photos' => 'PhotoController',
 
     'posts' => 'PostController'
 
     'posts' => 'PostController'
 
]);
 
]);
</syntaxhighlight>لإنشاء وحدة تحكّم مورد واجهة برمجيّة بسرعة ولا تتضمن التابعين create أو edit، استخدم المفتاح api-- (بمعنى switch) عند تنفيذ الأمر make:controller:<syntaxhighlight lang="php">
+
</syntaxhighlight>لإنشاء وحدة تحكّم مورد واجهة برمجيّة بسرعة ولا تتضمن التابعين <code>create</code> أو <code>edit</code>، استخدم المفتاح <code>api--</code> (بمعنى switch) عند تنفيذ الأمر <code>make:controller</code>:<syntaxhighlight lang="php">
 
php artisan make:controller API/PhotoController --api
 
php artisan make:controller API/PhotoController --api
  
سطر 207: سطر 207:
  
 
=== تسمية معاملات مسارات الموارد ===
 
=== تسمية معاملات مسارات الموارد ===
سينشئ Route::resource معاملات (parameters) المسار لمسارات مواردك استنادًا إلى الإصدار (version) "المُفرَّد" (singularized) من اسم المورد. يمكنك إعادة تعريف هذا بسهولة لكل مورد على انفراد باستخدام التابع parameters. يجب أن تكون المصفوفة المُمرّرة للتابع parameters مصفوفةً ترابطيّةً (associative array) لأسماء المصادر وأسماء المعاملات:<syntaxhighlight lang="php">
+
سينشئ <code>Route::resource</code> معاملات (parameters) المسار لمسارات مواردك استنادًا إلى الإصدار (version) "المُفرَّد" (singularized) من اسم المورد. يمكنك إعادة تعريف هذا بسهولة لكل مورد على انفراد باستخدام التابع parameters. يجب أن تكون المصفوفة المُمرّرة للتابع <code>parameters</code> مصفوفةً ترابطيّةً (associative array) لأسماء المصادر وأسماء المعاملات:<syntaxhighlight lang="php">
 
Route::resource('users', 'AdminUserController')->parameters([
 
Route::resource('users', 'AdminUserController')->parameters([
 
     'users' => 'admin_user'
 
     'users' => 'admin_user'
 
])
 
])
</syntaxhighlight>ينشئ المثال أعلاه عناوين روابط URI التالية لمسار المورد show:<syntaxhighlight lang="php">
+
</syntaxhighlight>ينشئ المثال أعلاه عناوين روابط URI التالية لمسار المورد <code>show</code>:<syntaxhighlight lang="php">
 
/users/{admin_user}
 
/users/{admin_user}
  
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
=== توطين روابط URIs الموارد ===
 +
سيُنشئ <code>Route::resource</code> افتراضيًّا روابط URIs للموارد باستخدام أفعال (verbs) انجليزية. إذا احتجت لترجمة أفعال الإجراء  <code>create</code> و <code>edit</code>، يمكنك استخدام التابع <code>Route::resourceVerbs</code>. يمكن القيام بذلك في التابع <code>boot</code> من <code>AppServiceProvider</code>:<syntaxhighlight lang="php">
 +
 +
use Illuminate\Support\Facades\Route;
 +
 +
/**
 +
* مهّد أي خدمة من التطبيق (Bootstrap)
 +
*
 +
* @return void
 +
*/
 +
public function boot()
 +
{
 +
    Route::resourceVerbs([
 +
        'create' => 'crear',
 +
        'edit' => 'editar',
 +
    ]);
 +
}
 +
 +
</syntaxhighlight>بمجرد أن تُخصّص الأفعال، سيُنتج تسجيل مسار مورد مثل <code>Route::resource('fotos', 'PhotoController')‎</code> العناوين URI التالية:<syntaxhighlight lang="php">
 +
/fotos/crear
 +
 +
/fotos/{foto}/editar
 +
</syntaxhighlight>
 +
 +
=== تكملة وحدات تحكّم الموارد ===
 +
إذا كنت بحاجة لإضافة مسارات لوحدة تحكّم مورد تتعدى مجموعة مسارات الموارد الافتراضية، عليك تعريف هذه المسارات قبل مناداتك <code>Route::resource</code>؛ وإلا قد تملك المسارات المُعرّفة من طرف تابع الموارد الأولويّة على المسارات التكميليّة من غير قصد:<syntaxhighlight lang="php">
 +
Route::get('photos/popular', 'PhotoController@method');
 +
 +
Route::resource('photos', 'PhotoController');
 +
</syntaxhighlight>'''ملاحظة''': تذكّر أن تُبقي وحدات تحكّمك مُركزّة. إن وجدت نفسك في حاجة لتوابع من خارج مجموعة أفعال الموارد الاعتيادية بشكل روتيني، ضع تقسيم وحدة تحكّمك لوحدتين أصغر بالحسبان.
 +
 +
== إضافة الاعتماديّات ووحدات التحكّم (Dependency Injection & Controllers) ==
 +
 +
=== إضافة التابع الباني Constructor ===
 +
يُستخدم حاوي خدمات [[Laravel]] لاستبيان كافة وحدات تحكّم Laravel. كنتيجة، يمكنك كتابة أية اعتماديّات قد تحتاجها وحدة تحكّمك في تابعها الباني. ستُستبين الاعتماديّات المُصرّح عنها تلقائيًّا ثم تضاف لنسخة وحدة التحكّم:<syntaxhighlight lang="php">
 +
<?php
 +
 +
namespace App\Http\Controllers;
 +
 +
use App\Repositories\UserRepository;
 +
 +
class UserController extends Controller
 +
{
 +
    /**
 +
    * نسخة مستودع المُستخدم
 +
    */
 +
    protected $users;
 +
 +
    /**
 +
    * إنشاء نسخة وحدة تحكّم جديدة
 +
    *
 +
    * @param  UserRepository  $users
 +
    * @return void
 +
    */
 +
    public function __construct(UserRepository $users)
 +
    {
 +
        $this->users = $users;
 +
    }
 +
}
 +
 +
</syntaxhighlight>يمكنك طبعا التلميح إلى نوع (type-hint) أي [[Laravel/contracts|عقد Laravel]] إذا أمكن للحاوي استبيانه (resolve) .قد تُوفّر إضافة اعتماديّاتك لوحدة تحكّمك قدرة اختبار أفضل.
 +
 +
=== إضافة التوابع ===
 +
إضافة للتابع الباني (constructor)، تستطيع التلميح أايضا على نوع الإعتماديّات في توابع وحدة تحكّمك. إضافة النسخة <code>Illuminate\Http\Request</code> لتوابع وحدة تحكّمك هي حالة استخدام شائعة لإضافة التوابع:<syntaxhighlight lang="php">
 +
<?php
 +
 +
namespace App\Http\Controllers;
 +
 +
use Illuminate\Http\Request;
 +
 +
class UserController extends Controller
 +
{
 +
    /**
 +
    * خزّن مستخدمًا جديدًا
 +
    *
 +
    * @param  Request  $request
 +
    * @return Response
 +
    */
 +
    public function store(Request $request)
 +
    {
 +
        $name = $request->name;
 +
 +
      //
 +
    }
 +
}
 +
 +
</syntaxhighlight>إن اشترط تابع وحدة تحكّمك أيضًا إدخالًا من معاملة مسار، أورد متغيّرات مسارك الوسيطة بعد اعتماديّاتك الأخرى. على سبيل المثال، إن عُرّف مسارك بهذا الشكل:<syntaxhighlight lang="php">
 +
Route::put('user/{id}', 'UserController@update');
 +
 +
</syntaxhighlight>تظل قادرًا على التلميح إلى نوع <code>Illuminate\Http\Request</code> وعلى الوصول لمعاملتك <code>id</code> عبر تعريف وحدة تحكّمك كما يلي:<syntaxhighlight lang="php">
 +
<?php
 +
 +
namespace App\Http\Controllers;
 +
 +
use Illuminate\Http\Request;
 +
 +
class UserController extends Controller
 +
{
 +
    /**
 +
    * تحديث المُستخدم المُحدّد
 +
    *
 +
    * @param  Request  $request
 +
    * @param  string  $id
 +
    * @return Response
 +
    */
 +
    public function update(Request $request, $id)
 +
    {
 +
      //
 +
    }
 +
}
 +
 +
</syntaxhighlight>'''ملاحظة''': لا يمكن تخزين المسارات المُستندة على نطاق مغلق (Closure) مؤقتًا. لاستخدام تخزين المسار المؤقّت، عليك تحويل أي مسارات نطاق مغلق لأصناف وحدات تحكّم.
 +
 +
إن استخدم تطبيقك المسارات المعتمدة على وحدات التحكّم حصرًا، عليك الاستفادة من ذاكرة تخزين المسار المؤقتة في [[Laravel]]. يُقلّص استخدام ذاكرة تخزين المسار المؤقتة الوقت اللازم لتسجيل جميع مسارات التطبيق بشكل جذري. قد ترتفع سرعة تسجيل مساراتك أكثر من 100 مرة  في بعض الحالات. لتوليد ذاكرة تخزين مؤقتة للمسار، ما عليك إلا تنفيذ أمر <code>Artisan route:cache</code>:<syntaxhighlight lang="php">
 +
php artisan route:cache
 +
 +
</syntaxhighlight>سيُحمّل ملف مساراتك المُخزّنة بعد تنفيذ هذا الأمر مع كل طلب. تذكّر إن أضفت أي مسارات جديدة ستحتاج إلى إنشاء ذاكرة تخزين مسارات مؤقتة جديدة. لهذا السبب، يجب فقط تنفيذ الأمر <code>route:cache</code> عند نشر (deployment) مشروعك.
 +
 +
يُمكنك استخدام الأمر <code>route:clear</code> لتفريغ ذاكرة تخزين المسار المؤقّتة:<syntaxhighlight lang="php">
 +
php artisan route:clear
 +
 +
</syntaxhighlight>
 +
 +
== مصادر ==
 +
* [https://laravel.com/docs/5.6/controllers صفحة Controllers في توثيق laravel الرسمي.]
 +
[[تصنيف:Laravel|{{SUBPAGENAME}}]]
 +
[[تصنيف:Laravel Basics|{{SUBPAGENAME}}]]

المراجعة الحالية بتاريخ 14:14، 24 أكتوبر 2018

مقدمة

بدلًا من تعريف كامل منطق معالجة طلباتك (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'
]);

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

اسم المسار الفعل العنوان URI الطريقة
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}

توطين روابط URIs الموارد

سيُنشئ Route::resource افتراضيًّا روابط URIs للموارد باستخدام أفعال (verbs) انجليزية. إذا احتجت لترجمة أفعال الإجراء  create و edit، يمكنك استخدام التابع Route::resourceVerbs. يمكن القيام بذلك في التابع boot من AppServiceProvider:

use Illuminate\Support\Facades\Route;

/**
 * مهّد أي خدمة من التطبيق (Bootstrap)
 *
 * @return void
 */
public function boot()
{
    Route::resourceVerbs([
        'create' => 'crear',
        'edit' => 'editar',
    ]);
}

بمجرد أن تُخصّص الأفعال، سيُنتج تسجيل مسار مورد مثل Route::resource('fotos', 'PhotoController')‎ العناوين URI التالية:

/fotos/crear

/fotos/{foto}/editar

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

إذا كنت بحاجة لإضافة مسارات لوحدة تحكّم مورد تتعدى مجموعة مسارات الموارد الافتراضية، عليك تعريف هذه المسارات قبل مناداتك Route::resource؛ وإلا قد تملك المسارات المُعرّفة من طرف تابع الموارد الأولويّة على المسارات التكميليّة من غير قصد:

Route::get('photos/popular', 'PhotoController@method');

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

ملاحظة: تذكّر أن تُبقي وحدات تحكّمك مُركزّة. إن وجدت نفسك في حاجة لتوابع من خارج مجموعة أفعال الموارد الاعتيادية بشكل روتيني، ضع تقسيم وحدة تحكّمك لوحدتين أصغر بالحسبان.

إضافة الاعتماديّات ووحدات التحكّم (Dependency Injection & Controllers)

إضافة التابع الباني Constructor

يُستخدم حاوي خدمات Laravel لاستبيان كافة وحدات تحكّم Laravel. كنتيجة، يمكنك كتابة أية اعتماديّات قد تحتاجها وحدة تحكّمك في تابعها الباني. ستُستبين الاعتماديّات المُصرّح عنها تلقائيًّا ثم تضاف لنسخة وحدة التحكّم:

<?php

namespace App\Http\Controllers;

use App\Repositories\UserRepository;

class UserController extends Controller
{
    /**
     * نسخة مستودع المُستخدم
     */
    protected $users;

    /**
     * إنشاء نسخة وحدة تحكّم جديدة
     *
     * @param  UserRepository  $users
     * @return void
     */
    public function __construct(UserRepository $users)
    {
        $this->users = $users;
    }
}

يمكنك طبعا التلميح إلى نوع (type-hint) أي عقد Laravel إذا أمكن للحاوي استبيانه (resolve) .قد تُوفّر إضافة اعتماديّاتك لوحدة تحكّمك قدرة اختبار أفضل.

إضافة التوابع

إضافة للتابع الباني (constructor)، تستطيع التلميح أايضا على نوع الإعتماديّات في توابع وحدة تحكّمك. إضافة النسخة Illuminate\Http\Request لتوابع وحدة تحكّمك هي حالة استخدام شائعة لإضافة التوابع:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class UserController extends Controller
{
    /**
     * خزّن مستخدمًا جديدًا
     *
     * @param  Request  $request
     * @return Response
     */
    public function store(Request $request)
    {
        $name = $request->name;

       //
    }
}

إن اشترط تابع وحدة تحكّمك أيضًا إدخالًا من معاملة مسار، أورد متغيّرات مسارك الوسيطة بعد اعتماديّاتك الأخرى. على سبيل المثال، إن عُرّف مسارك بهذا الشكل:

Route::put('user/{id}', 'UserController@update');

تظل قادرًا على التلميح إلى نوع Illuminate\Http\Request وعلى الوصول لمعاملتك id عبر تعريف وحدة تحكّمك كما يلي:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class UserController extends Controller
{
    /**
     * تحديث المُستخدم المُحدّد
     *
     * @param  Request  $request
     * @param  string  $id
     * @return Response
     */
    public function update(Request $request, $id)
    {
       //
    }
}

ملاحظة: لا يمكن تخزين المسارات المُستندة على نطاق مغلق (Closure) مؤقتًا. لاستخدام تخزين المسار المؤقّت، عليك تحويل أي مسارات نطاق مغلق لأصناف وحدات تحكّم. إن استخدم تطبيقك المسارات المعتمدة على وحدات التحكّم حصرًا، عليك الاستفادة من ذاكرة تخزين المسار المؤقتة في Laravel. يُقلّص استخدام ذاكرة تخزين المسار المؤقتة الوقت اللازم لتسجيل جميع مسارات التطبيق بشكل جذري. قد ترتفع سرعة تسجيل مساراتك أكثر من 100 مرة  في بعض الحالات. لتوليد ذاكرة تخزين مؤقتة للمسار، ما عليك إلا تنفيذ أمر Artisan route:cache:

php artisan route:cache

سيُحمّل ملف مساراتك المُخزّنة بعد تنفيذ هذا الأمر مع كل طلب. تذكّر إن أضفت أي مسارات جديدة ستحتاج إلى إنشاء ذاكرة تخزين مسارات مؤقتة جديدة. لهذا السبب، يجب فقط تنفيذ الأمر route:cache عند نشر (deployment) مشروعك. يُمكنك استخدام الأمر route:clear لتفريغ ذاكرة تخزين المسار المؤقّتة:

php artisan route:clear

مصادر