بنية Laravel 11 ودورة حياة الطلب (Request Lifecycle)

هذا الدرس مختلف قليلاً عن البقية — لن نكتب كوداً كثيراً. بدلاً من ذلك، سنفهم كيف يفكر Laravel من الداخل. لماذا هذا مهم؟ لأن كل مشكلة ستواجهها لاحقاً — خطأ غامض، سلوك غير متوقع، سؤال لماذا لا يعمل الكود — ستكون إجابته في فهم هذا الدرس.

1. السؤال الذي يتجاهله الجميع: ماذا يحدث بعد الضغط على Enter؟

أنت تفتح المتصفح وتكتب http://127.0.0.1:8000/articles وتضغط Enter. ظهرت لك قائمة المقالات. الواجهة تبدو بسيطة — لكن ما الذي حدث خلف الكواليس خلال أجزاء من الثانية؟

كثير من الطلاب يتعلمون Laravel وينجحون في بناء مشاريع دون أن يعرفوا إجابة هذا السؤال. وهذا مقبول في البداية. لكن عندما يواجهون مشكلة في الـ Middleware أو يريدون إنشاء Service Provider خاص بهم، يجدون أنفسهم تائهين. هذا الدرس يمنعك من الوقوع في هذا الموقف.

القصة القصيرة: عندما يصل طلبك إلى Laravel، يمر بـ خمس محطات رئيسية قبل أن تظهر لك الصفحة على الشاشة. لنشرحها واحدة واحدة بطريقة إنسانية لا تقنية.

2. المحطة الأولى: ملف public/index.php — الباب الوحيد

تخيّل مبنى حكومي كبير فيه عشرات الأقسام. لكن له مدخل رئيسي واحد فقط — لا يمكن لأحد الدخول إلا من خلاله. عند هذا المدخل يوجد حارس أمن يسجّل كل شخص داخل ويحوّله للقسم المناسب.

هذا بالضبط ما يفعله ملف public/index.php في Laravel. كل طلب يصل إلى موقعك — بغض النظر عن الرابط — يمر عبر هذا الملف أولاً. إذا طلبت /articles أو /users/5 أو /contact، الكل يمر من هنا.

هذا الملف يفعل شيئين فقط:

  1. يحمّل Composer Autoloader — وهو الملف الذي يعلّم PHP كيف تجد وتحمّل أي كلاس في المشروع تلقائياً بدون أن تكتب require يدوياً في كل مكان.
  2. يسلّم الطلب إلى نواة التطبيق (Kernel) لتبدأ عملية المعالجة الفعلية.
public/index.php — المحتوى المُبسَّط
// 1. تحميل كل كلاسات المشروع تلقائياً
require __DIR__.'/../vendor/autoload.php';

// 2. تحميل التطبيق نفسه
$app = require_once __DIR__.'/../bootstrap/app.php';

// 3. تسليم الطلب للمعالجة وإرجاع الاستجابة
$response = $app->handleRequest(Request::capture());
$response->send();
لماذا ملف واحد للكل؟
هذا النمط يُسمى Front Controller Pattern. فائدته أن كل إعدادات الأمان والتسجيل والمعالجة الأولية تحدث في مكان واحد، مما يجعل الصيانة أسهل بكثير من وجود مئات الملفات PHP كل منها يدير نفسه.

3. المحطة الثانية: HTTP Kernel — مدير العمليات

تخيّل الـ Kernel (النواة) كمدير مطعم كبير. عندما يدخل زبون (الطلب)، المدير لا يذهب فوراً ليطبخ الطعام. أولاً يتأكد من الاستعداد الكامل للمطعم: هل الطاولات جاهزة؟ هل الطاخون حاضرون؟ هل الصحون نظيفة؟ ثم يوجّه الزبون للطاولة المناسبة.

الـ HTTP Kernel يفعل نفس الشيء — يتأكد أن التطبيق كلّه مُعدّ ومجهّز قبل معالجة الطلب:

  • يحمّل ملفات الإعداد المحفوظة في مجلد config/ (قاعدة البيانات، البريد، التخزين...).
  • يُعدّ نظام اكتشاف الأخطاء ومعالجتها.
  • يضبط المنطقة الزمنية ولغة التطبيق من ملف .env.
  • يُشغّل جميع الـ Service Providers (سنشرحها في الخطوة التالية).
  • يمرّر الطلب عبر قائمة الـ Middleware.
ملاحظة مهمة: لن تحتاج لتعديل الـ Kernel في معظم مشاريعك. لكن فهم وجوده يشرح لك لماذا تظهر إعداداتك من ملف .env تلقائياً في كل مكان في الكود دون أن تستدعيها بنفسك.

4. المحطة الثالثة: Service Providers — من يُشغّل كل شيء؟

هذا هو أكثر جزء يُربك الطلاب في Laravel. دعني أشرحه بطريقة مختلفة تماماً.

تخيّل أنك وصلت إلى مكتبك في الصباح. قبل أن تبدأ العمل، تفعل روتيناً معيناً: تفتح الكمبيوتر ← تفتح بريدك ← تفتح مشروعك ← تفتح أدوات التطوير. هذا الروتين هو ما يجعلك مستعداً للعمل.

Service Providers هي روتين الصباح لـ Laravel. كل Provider مسؤول عن "إيقاظ" جزء معين من التطبيق وجعله جاهزاً للاستخدام:

  • DatabaseServiceProvider — يفتح الاتصال بقاعدة البيانات
  • MailServiceProvider — يُجهّز نظام إرسال البريد الإلكتروني
  • AuthServiceProvider — يُحضّر نظام المصادقة والصلاحيات
  • RouteServiceProvider — يحمّل ملفات الـ Routes

كل هذا يحدث قبل أن يصل طلبك إلى أي متحكم (Controller). عندما يصل الطلب أخيراً للكود الذي كتبته أنت، كل الأدوات التي تحتاجها جاهزة للاستخدام.

متى ستحتاج لإنشاء Service Provider خاص بك؟
عندما تبني حزمة (Package) أو تريد تسجيل شيء في التطبيق يحتاج أن يكون "جاهزاً" دائماً عند بدء التشغيل. في المشاريع الصغيرة والمتوسطة، ستستخدم الـ Providers الموجودة ولن تحتاج لإنشاء واحد جديد.

5. المحطة الرابعة: Middleware — بوابات الفحص

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

Middleware في Laravel يعمل بنفس المنطق. هي طبقات تفحص الطلب قبل الوصول للـ Controller، وتفحص الاستجابة قبل إرسالها للمستخدم.

أمثلة على Middleware موجودة في كل مشروع Laravel:

  • auth: يتحقق أن المستخدم سجّل دخوله قبل السماح له بالوصول. إذا لم يسجّل، يعيد توجيهه تلقائياً لصفحة Login.
  • csrf: يتأكد أن الطلب جاء من النموذج الحقيقي في موقعك وليس من موقع آخر (حماية CSRF).
  • throttle: يمنع أي مستخدم من إرسال أكثر من عدد معين من الطلبات في الدقيقة (حماية من هجمات Brute Force).
routes/web.php — تطبيق Middleware
// هذا المسار يشترط تسجيل الدخول — سيتحقق Middleware تلقائياً
Route::get('/dashboard', [DashboardController::class, 'index'])
    ->middleware('auth');

// يمكن تطبيق أكثر من Middleware دفعةً واحدة
Route::get('/admin', [AdminController::class, 'index'])
    ->middleware(['auth', 'admin']);
الاتجاهان: Middleware يعمل باتجاهين — "قبل" الوصول للـ Controller (مثل التحقق من الدخول) و"بعد" الـ Controller وقبل إرسال الاستجابة (مثل إضافة headers أمنية للصفحة). ستتعلم كتابة Middleware خاص بك في درس مخصص لاحقاً.

6. المحطة الخامسة: Router ← Controller ← Response — الوجهة النهائية

بعد اجتياز كل نقاط الفحص، وصل الطلب أخيراً للمرحلة التي كتبتَ فيها كودك:

أولاً — Router: أين تذهب يا طلب؟

الـ Router يبحث في ملفات routes/web.php أو routes/api.php عن الرابط المطابق لما طلبه المستخدم. إذا وجد المطابقة، يوجّه الطلب للكود المحدد. إذا لم يجد — يُرجع صفحة 404 Not Found تلقائياً.

php artisan route:list

هذا الأمر يعرض لك قائمة بكل Routes المسجّلة في مشروعك — مفيد جداً للتشخيص.

ثانياً — Controller: هنا كودك يعمل

المتحكم (Controller) هو المكان الذي تكتب فيه منطق تطبيقك. هنا تجلب البيانات من قاعدة البيانات، تعالجها، وترسل النتيجة للعرض.

app/Http/Controllers/ArticleController.php
class ArticleController extends Controller
{
    public function index()
    {
        // جلب كل المقالات من قاعدة البيانات
        $articles = Article::latest()->get();

        // إرسالها إلى صفحة العرض (View)
        return view('articles.index', compact('articles'));
    }
}

ثالثاً — Response: الرحلة العكسية

بعد أن ينفّذ Controller عمله، يُرجع استجابة (Response). هذه الاستجابة تسلك نفس الطريق معكوساً: تمر عبر Middleware مرة أخرى (باتجاه الخروج)، ثم يرسلها Kernel للمستخدم، وأخيراً يعرضها المتصفح على الشاشة.

Response يمكن أن تكون:

  • صفحة HTML: عبر return view('articles.index', $data);
  • JSON: عبر return response()->json($data); (للـ API)
  • إعادة توجيه: عبر return redirect('/home');
  • ملف للتحميل: عبر return response()->download($path);

7. الصورة الكاملة لدورة حياة الطلب في Laravel

الآن لنجمع كل ما تعلمناه في تسلسل واضح:

دورة حياة الطلب — من البداية للنهاية
المتصفح يرسل طلب GET /articles
        ↓
public/index.php  ← نقطة الدخول الوحيدة
        ↓
HTTP Kernel  ← إعداد التطبيق والبيئة
        ↓
Service Providers  ← تشغيل قاعدة بيانات، بريد، auth...
        ↓
Middleware (قبل)  ← هل المستخدم مسجّل دخوله؟ هل الطلب آمن؟
        ↓
Router  ← أي Controller يعالج هذا الرابط؟
        ↓
Controller  ← جلب البيانات + منطق الأعمال
        ↓
View (Blade)  ← تحويل البيانات إلى HTML
        ↓
Middleware (بعد)  ← إضافة Headers، ضغط الاستجابة...
        ↓
المتصفح يعرض الصفحة ✓
هذا هو "الخريطة" التي تحتاجها دائماً. في أي وقت تواجه مشكلة في Laravel، اسأل نفسك: "في أي محطة من هذه المحطات تحدث المشكلة؟" هذا السؤال وحده يوفّر عليك ساعات من البحث العشوائي.

8. Service Container — المفهوم الذي يخيف الجميع (لكنه بسيط)

الـ Service Container هو المفهوم الأكثر إرباكاً في Laravel للمبتدئين. لكن في الحقيقة هو بسيط جداً عرفت مثاله.

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

في Laravel، هذا يعني أنك في الـ Controller لا تحتاج لكتابة:

بدون Service Container (مؤلم) مقابل معه (أنيق)
// ❌ بدون Service Container — تُنشئ كل شيء يدوياً
class ArticleController extends Controller {
    public function __construct() {
        $db = new DatabaseConnection('host', 'user', 'pass', 'db');
        $this->repo = new ArticleRepository($db);
        $this->mailer = new Mailer(new SmtpTransport('host', 587));
    }
}

// ✅ مع Service Container — تطلب فقط وLaravel يجلب
class ArticleController extends Controller {
    public function __construct(
        private ArticleRepository $repo,
        private Mailer $mailer
    ) {
        // Laravel ينشئ هذه الكائنات ويمررها تلقائياً
    }
}

هذا المفهوم يُسمى Dependency Injection — ستتعامل معه بشكل تلقائي في Laravel حتى لو لم تعرف اسمه. Laravel يديره في الخلفية دون أن تضطر لإعداده بنفسك.

أسئلة شائعة عن بنية Laravel ودورة حياة الطلب

هذه أسئلة طرحها طلاب حقيقيون بعد قراءة هذا الدرس:

سؤال ذكي. المنطق المعاكس في الواقع هو الصحيح: ملف واحد = أسرع وأأمن. كل الإعداد يحدث مرة واحدة في مكان واحد. بدلاً من أن كل صفحة تحمّل إعداداتها الخاصة (مما يرفع احتمال الأخطاء والتكرار)، مشاريع PHP الكبيرة مثل Symfony وYii2 وCakePHP كلها تستخدم نفس النمط (Front Controller Pattern).

لا. يمكنك بناء مشاريع Laravel كاملة دون أن تتعمق في Service Container. الإجابة الإجمالية: تعامل معه عندما تحتاجه. ستستخدمه بشكل تلقائي عبر Type Hinting في الـ Controllers دون أن تدرك ذلك. الفهم العميق يأتي لاحقاً عند بناء Packages أو تطبيقات ضخمة.

الفرق في المسؤولية والتوقيت:

  • Middleware: يعمل قبل الـ Controller. مسؤوليته الفحص والتصفية (هل المستخدم مصرّح له؟ هل الطلب صالح؟). إذا فشل الفحص — لا يصل الطلب للـ Controller أصلاً.
  • Controller: يعمل بعد Middleware. مسؤوليته منطق الأعمال (جلب البيانات، المعالجة، إعداد الاستجابة).

جزئياً — نعم. مثلاً يمكنك إخراج Route معين من Middleware معين باستخدام withoutMiddleware(). لكن الـ Kernel وService Providers يعملان دائماً لأنهما ضروريان لتشغيل التطبيق أصلاً. هذا التصميم يضمن أن التطبيق دائماً في حالة مُعدَّة وآمنة.

الدرس القادم

هيكل مجلدات مشروع Laravel — وظيفة كل ملف 📁

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

اكتشف هيكل المجلدات
المحرر الذكي

اكتب الكود وشاهد النتيجة فوراً

جرب الآن مجاناً
قناة ديف عربي

تابع أحدث الدروس والتحديثات مباشرة على واتساب

انضم الآن