المتحكمات في Laravel: Controllers
في الدرس السابق كتبت الكود داخل المسارات مباشرة. هذا جميل لمسار أو اثنين، لكن تخيّل تطبيقاً فيه خمسون صفحة، وكل صفحة فيها منطق طويل: سيتحول routes/web.php إلى ملف ضخم مزدحم. المتحكمات (Controllers) تحل هذه المشكلة بتنظيم الكود في كلاسات مرتبة. وهي حرف C في نمط MVC الذي تعرفت عليه في الدرس الأول.
ما هو الـ Controller؟
Section titled “ما هو الـ Controller؟”المتحكم كلاس فيه مجموعة دوال (تسمى Actions)، كل دالة مسؤولة عن صفحة أو عملية واحدة. وعادة نجمع العمليات المتعلقة بنفس الشيء في متحكم واحد: كل ما يخص المقالات في PostController، وكل ما يخص المستخدمين في UserController.
تذكّر تشبيه المطعم: المتحكم هو النادل. يستقبل طلبك (Request)، ويذهب للمطبخ (Model) ليجلب الطعام، ثم يقدمه لك في طبق جميل (View). وكل نادل مسؤول عن مجموعة طاولات محددة.
إنشاء متحكم
Section titled “إنشاء متحكم”لا تكتب الملف بيدك، بل اطلبه من Artisan:
php artisan make:controller PostControllerسينشئ الملف app/Http/Controllers/PostController.php:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class PostController extends Controller{ //}namespace: مكان الكلاس في المشروع، مثل عنوان البيت.extends Controller: يرث من المتحكم الأساسي في Laravel.- اسم المتحكم بصيغة PascalCase وينتهي بكلمة
Controller، وهذا عُرف يلتزم به كل مطوري Laravel.
أول Action
Section titled “أول Action”نضيف دالة تعرض قائمة المقالات:
class PostController extends Controller{ public function index() { return 'هنا ستظهر كل المقالات'; }}ثم نربطها بمسار في routes/web.php:
<?php
use App\Http\Controllers\PostController;use Illuminate\Support\Facades\Route;
Route::get('/posts', [PostController::class, 'index'])->name('posts.index');بدلاً من الدالة المجهولة، نعطي المسار مصفوفة فيها اسم الكلاس واسم الدالة. اقرأها: «عندما يطلب الزائر /posts، نفّذ الدالة index في PostController». ولا تنسَ سطر use في الأعلى ليعرف الملف مكان الكلاس.
استقبال معاملات الرابط
Section titled “استقبال معاملات الرابط”معامل المسار يصل إلى دالة المتحكم تماماً كما كان يصل للدالة المجهولة:
Route::get('/posts/{id}', [PostController::class, 'show'])->name('posts.show');public function show(int $id){ return "المقال رقم $id";}اسم المتغير في الدالة يطابق اسم المعامل في المسار {id}.
استقبال بيانات الطلب
Section titled “استقبال بيانات الطلب”لقراءة بيانات نموذج أو رابط، أضف معاملاً من نوع Request، وسيمرره Laravel تلقائياً:
use Illuminate\Http\Request;
public function store(Request $request){ $title = $request->input('title'); // ...}$request->input('title') تقرأ الحقل title سواء أُرسل بـ GET أو POST. هذا أنظف وأأمن من التعامل مع $_POST مباشرة كما كنت تفعل في PHP العادية. وهذه الميزة التي «يمرر فيها Laravel ما تحتاجه تلقائياً» تسمى حقن الاعتماديات (Dependency Injection)، وستراها كثيراً.
من المتحكم إلى الصفحة
Section titled “من المتحكم إلى الصفحة”في التطبيق الحقيقي، المتحكم لا يُرجع نصاً، بل يجهّز البيانات ويرسلها إلى View:
public function index(){ $posts = ['أول مقال', 'مقال ثانٍ'];
return view('posts.index', ['posts' => $posts]);}الدالة view('posts.index') تعرض الملف resources/views/posts/index.blade.php، والمصفوفة الثانية فيها البيانات التي ستصل للصفحة. ويمكن كتابة نفس الشيء باختصار بالدالة compact:
return view('posts.show', compact('post'));// تساوي: ['post' => $post]ستتعلم كتابة ملفات الـ View في الدرس القادم، وجلب البيانات الحقيقية من قاعدة البيانات في الدرس الذي بعده.
متحكمات الموارد (Resource Controllers)
Section titled “متحكمات الموارد (Resource Controllers)”أغلب أجزاء التطبيقات تحتاج نفس العمليات: عرض القائمة، وعرض عنصر واحد، والإنشاء، والتعديل، والحذف. هذه تسمى عمليات CRUD (Create, Read, Update, Delete). Laravel ينشئ لك متحكماً جاهزاً بها كلها:
php artisan make:controller CourseController --resourceسيأتي المتحكم بسبع دوال فارغة جاهزة:
| الدالة | وظيفتها |
|---|---|
index |
عرض كل العناصر |
create |
عرض نموذج إضافة عنصر |
store |
حفظ العنصر الجديد |
show |
عرض عنصر واحد |
edit |
عرض نموذج التعديل |
update |
حفظ التعديل |
destroy |
حذف العنصر |
وتربطها كلها بسطر واحد في المسارات:
Route::resource('courses', CourseController::class);هذا السطر ينشئ سبعة مسارات بأسمائها، مثل courses.index و courses.store. شغّل php artisan route:list لتراها.
جرّب بنفسك
Section titled “جرّب بنفسك”- أنشئ
PostControllerبأمر artisan. - أضف الدالة
indexتُرجع «كل المقالات»، والدالةshow(int $id)تُرجع «المقال رقم …». - اربطهما بالمسارين
/postsو/posts/{id}مع أسماءposts.indexوposts.show. - شغّل
php artisan route:list --path=postsوتأكد أن المسارين يظهران مع اسم المتحكم. - تحدٍّ: أنشئ
CourseControllerبـ--resource، واربطه بـRoute::resource، ثم عدّ المسارات الجديدة.
أخطاء شائعة
Section titled “أخطاء شائعة”- نسيان سطر use للمتحكم في routes/web.php: يظهر خطأ أن الكلاس غير موجود
Target class [PostController] does not exist. - اختلاف اسم الدالة بين المسار والمتحكم:
'index'في المسار وfunction list()في المتحكم لا يعملان معاً. - وضع كل المنطق في المتحكم: متحكم بمئات الأسطر علامة على أن الكود يحتاج تقسيماً.
اختبر نفسك
Section titled “اختبر نفسك”سؤال
كيف تربط المسار /posts بالدالة index في PostController؟
نمرر مصفوفة فيها اسم الكلاس واسم الدالة، مع سطر use للمتحكم في أعلى الملف.
سؤال
أي دالة في متحكم الموارد مسؤولة عن حفظ عنصر جديد بعد إرسال النموذج؟
create تعرض النموذج فقط، و store تستقبل بياناته وتحفظها، و update لحفظ التعديل.
الخلاصة
Section titled “الخلاصة”- المتحكم كلاس ينظّم منطق الصفحات بدل تكديسه في المسارات.
- تنشئه بـ
php artisan make:controllerوتربطه بـ[PostController::class, 'index']. - معاملات الرابط تصل للدالة باسمها، و
Request $requestلقراءة بيانات الطلب. - المتحكم يرسل البيانات للصفحة بـ
view('name', [...]). --resourceوRoute::resourceيجهّزان العمليات السبع لـ CRUD دفعة واحدة.