انتقل إلى محتوى الدرس
الدرس 41
دورة إطار العمل Laravel

التحميل المسبق وحل مشكلة استعلامات N Plus 1 في EloquentEager Loading with and Solving the N Plus 1 Query Problem

تشخيص مشكلة الأداء N+1 Query الناتجة عن التحميل الكسول وحلها جذرياً عبر التحميل المسبق بالدالة with ومنع التحميل الكسول.
أقسام الدرس
6
الأمثلة
6
اللغة
العربية
تاريخ النشر
غير محدد
المشاهدات
0
محتوى الدرس
في هذا الدرس 6تصفّح المواضيع

تعتمد علاقات Eloquent افتراضياً على التحميل الكسول، أي أن السجلات المرتبطة لا يتم جلبها من قاعدة البيانات إلا لحظة قراءة خاصية العلاقة فعلياً في الكود. عند الدوران على 50 مقالاً وقراءة اسم المؤلف داخل الحلقة، ينفذ الإطار استعلاماً واحداً للمقالات متبوعاً بـ 50 استعلاماً منفصلاً لكل مؤلف، مما يسبب اختناق الأداء المعروف بمشكلة N+1.

  • الجلب عند الطلب (Lazy Loading): لا يتم تنفيذ استعلام العلاقة إلا عند قراءة الخاصية الديناميكية لأول مرة.
  • مضاعف الاستعلامات (N+1 Queries): استعلام واحد للآباء يتبعه N استعلام داخل الحلقة لكل سجل فرعي على حدة.
  • البطء الخفي في الإنتاج (Production Bottleneck): لا يظهر أثره مع 3 سجلات محلياً لكنه يبطئ الخادم بشدة عند نمو البيانات.
مخطط معماري يوضح التحميل المسبق وحل مشكلة استعلامات N Plus 1 في Eloquent في إطار العمل Laravel 12
PHP
// Bad: Triggers 1 + N queries!
$posts = Post::all();

foreach ($posts as $post) {
    $author = $post->user->name;
}

يحل التحميل المسبق مشكلة استعلامات N+1 جذرياً عبر تحديد العلاقات المطلوب جلبها مسبقاً باستخدام دالة with قبل تنفيذ الاستعلام. بدلاً من إطلاق عشرات الاستعلامات داخل الحلقة، يجمع Eloquent كافة المفاتيح الأجنبية من الاستعلام الأول ويجلب جميع السجلات المرتبطة باستعلام ثانٍ واحد فقط يستخدم جملة WHERE IN.

  • ثبات عدد الاستعلامات (Constant 2 Queries): سواء عرضت 10 مقالات أو 1000 مقال مع مؤلفيها، ينفذ النظام استعلامين اثنين فقط.
  • تعدد العلاقات (Multiple Relations): تقبل دالة with اسم علاقة مفردة أو مصفوفة علاقات لتحميلها معاً بكفاءة.
  • انعدام استعلامات الحلقة (In-Memory Access): قراءة العلاقة داخل حلقة التكرار تتم فوراً من الذاكرة المحملة مسبقاً.
PHP
// Good: Runs only 2 queries total!
$posts = Post::with(['user', 'tags'])->get();

foreach ($posts as $post) {
    $author = $post->user->name;
}

يمكنك تطبيق التحميل المسبق على العلاقات المتداخلة عبر عدة نماذج باستخدام الصيغة النقطية، مثل تحميل مؤلف المقال وملفه الشخصي معاً عبر user.profile. ولتقليل استهلاك الذاكرة بشكل أكبر، حدد الأعمدة المطلوبة فقط بعد نقطتين رأسيتين مثل user:id,name مع الالتزام الدائم بتضمين عمود المعرف الأساسي.

  • التداخل بالصيغة النقطية (Dot Notation): حمّل العلاقات الفرعية المتسلسلة بسهولة عبر كتابة مسار العلاقة مفصولاً بنقطة.
  • اختيار أعمدة محددة (Column Selection): حدد أسماء الأعمدة المطلوبة بعد النقطتين لتجنب جلب النصوص الطويلة غير اللازمة.
  • إلزامية مفاتيح الربط (Key Requirement): احرص دائماً على تضمين عمود id ومفتاح الربط الأجنبي وإلا ستعود العلاقة فارغة.
PHP
$posts = Post::with([
    'user:id,name',
    'comments.author:id,name',
])->get();

عندما تحتاج لتصفية أو ترتيب السجلات داخل العلاقة المحملة مسبقاً نفسها، مرر مصفوفة ترابطية إلى دالة with يكون مفتاحها اسم العلاقة وقيمتها دالة مغلقة تخصص الاستعلام. أما إذا كان كائن النموذج الأب محملاً مسبقاً في الذاكرة، فاستخدم دالتي load أو loadMissing لتحميل علاقاته لاحقاً بكفاءة.

  • تقييد التحميل المسبق (Constrained with): صفِّ أو رتب السجلات المرتبطة داخل دالة with المغلقة دون التأثير على نتائج النموذج الأب.
  • التحميل اللاحق (load Method): يحمل العلاقات مسبقاً لكائن نموذج أو مجموعة نماذج موجودة بالفعل في الذاكرة.
  • التحميل الذكي بدون تكرار (loadMissing): يجلب العلاقة فقط إذا لم تكن قد حُملت مسبقاً خلال دورة الطلب الحالية.
PHP
$posts = Post::with(['comments' => function ($q) {
    $q->where('is_approved', true)->latest();
}])->get();

$post->loadMissing('tags');

لاكتشاف استعلامات N+1 غير المقصودة مبكراً قبل وصول الكود إلى بيئة الإنتاج، يتيح لك Laravel تعطيل التحميل الكسول كلياً عبر استدعاء Model::preventLazyLoading داخل المزود AppServiceProvider. تمرير شرط عدم كون البيئة إنتاجية يطلق استثناءً واضحاً ينبه المبرمج فوراً أثناء التطوير مع الحفاظ على استمرار عمل الموقع في الإنتاج.

  • منع التحميل الكسول (preventLazyLoading): يأمر Eloquent بإطلاق استثناء تنبيهي فور محاولة قراءة علاقة لم يتم تحميلها مسبقاً.
  • الربط ببيئة التطوير (Non-Production Guard): تفعيله في غير بيئة الإنتاج يكشف أخطاء الأداء للمطور فوراً دون تعطيل الزوار الفعليين.
  • الوضع الصارم الشامل (Model::shouldBeStrict): يفعل منع التحميل الكسول ويمنع تجاهل الحقول غير القابلة للتعبئة بصمت.
PHP
use Illuminate\Database\Eloquent\Model;

public function boot(): void
{
    Model::preventLazyLoading(
        ! $this->app->isProduction()
    );
}

يُعد القضاء على مشكلة استعلامات N+1 عبر التحميل المسبق أهم خطوة لتحسين أداء قواعد البيانات في التطوير اليومي بتطبيقات Laravel. يضمن الجمع بين استدعاء دالة with صراحة في المتحكمات وتفعيل preventLazyLoading أثناء التطوير ثبات عدد الاستعلامات مهما تضخم حجم البيانات.

وجه المقارنة الهندسيالأسلوب اليدوي أو غير المحسنمعيار Laravel 12 الحديث
الدوران على العلاقاتقراءة اسم المؤلف مباشرة بعد Post::all مما يولد N+1 استعلاماًالتحميل المسبق عبر Post::with('user:id,name') باستعلامين فقط
العلاقات المتداخلةإطلاق سلسلة استعلامات كسولة متتالية عبر ثلاثة جداولاستخدام الصيغة النقطية with('comments.author') لتحميلها معاً
نموذج أب محمل مسبقاًكتابة استعلام منفصل لجلب الأبناء بمعرف الأب يدوياًاستدعاء دالة loadMissing على الكائن المحمل عند الحاجة
اكتشاف أخطاء الأداءانتظار شكاوى البطء في خادم الإنتاج الحي بعد النشرتفعيل Model::preventLazyLoading في بيئة التطوير المحلية
PHP
$posts = Post::with(['user:id,name', 'tags'])
    ->withCount('comments')
    ->latest()
    ->get();
خلاصة المعرفة ومحطة الانتقال

ملخص الدرس

حصاد الدرس

مراجعة مركّزة لأهم المفاهيم والقواعد الهندسية التي أتقنتها في هذا الدرس قبل التطبيق العملي

ماذا تعلّمت في هذا الدرس؟

أتقنت في هذا الدرس حول «التحميل المسبق وحل مشكلة استعلامات N Plus 1 في Eloquent» مفاهيم التحميل الكسول ومشكلة استعلامات N1، والتحميل المسبق للعلاقات بدالة With، والتحميل المتداخل وتحديد الأعمدة وفق معايير Laravel 12 الحديثة.

الخطوة التالية والدرس القادم

انتقل الآن إلى الدرس التالي «ربط النماذج بالمسارات وترقيم الصفحات في Eloquent» للبناء التراكمي على ما تعلمته.

مشاركة

هل كان هذا الدرس مفيدًا؟

جارٍ تحميل الآراء…

ابنِ لغتك البرمجية

المصطلحات4

راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.

0 / 4 مفهومةأول بطاقة، أول خطوة
01 Eager Loading التحميل المسبق
تشخيص مشكلة الأداء N+1 Query الناتجة عن التحميل الكسول وحلها جذرياً عبر التحميل المسبق بالدالة with ومنع التحميل الكسول.
للمراجعة
02 Lazy Loading and Query Bottlenecks التحميل الكسول ومشكلة استعلامات N1
المفهوم الهندسي والتطبيق العملي المباشر لقسم التحميل الكسول ومشكلة استعلامات N1 في إطار العمل Laravel 12.
للمراجعة
03 Eager Loading Relations With Method التحميل المسبق للعلاقات بدالة With
المفهوم الهندسي والتطبيق العملي المباشر لقسم التحميل المسبق للعلاقات بدالة With في إطار العمل Laravel 12.
للمراجعة
04 Nested and Specific Column Loading التحميل المتداخل وتحديد الأعمدة
المفهوم الهندسي والتطبيق العملي المباشر لقسم التحميل المتداخل وتحديد الأعمدة في إطار العمل Laravel 12.
للمراجعة

اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.

حروف قليلة. معنى كامل.

الاختصارات4

راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.

0 / 4 مفهومةأول بطاقة، أول خطوة
01 MVC MVC
Model View Controller
النمط المعماري الذي يفصل بين نماذج البيانات Models، وطبقات العرض Views، والمتحكمات Controllers في Laravel.
للمراجعة
02 CLI CLI
Command Line Interface
واجهة سطر الأوامر التي تعمل عبر أداة php artisan لتوليد الملفات وإدارة التطبيق.
للمراجعة
03 HTTP HTTP
Hypertext Transfer Protocol
بروتوكول نقل النص الفائق الذي ينظم طلبات المتصفح واستجابات خادم Laravel.
للمراجعة
04 PSR PSR
PHP Standards Recommendations
المعايير القياسية للغة PHP مثل التحميل التلقائي PSR-4 التي يلتزم بها إطار العمل Laravel.
للمراجعة

اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.

من الفهم للتطبيق

مهامك قبل الاختبار

خطوة صغيرة كل مرة. وإنجاز تقدر ترجع له.

0/2مهام منجزة
  1. اكتب ونفّذ المثال البرمجي المشروح في قسم «التحميل الكسول ومشكلة استعلامات N1» داخل مشروع Laravel 12 المحلي وتحقق من النتيجة.

  2. بدّل بين الحالات الثلاث في المحاكي التفاعلي ضمن قسم «التحميل المسبق للعلاقات بدالة With» وقارن مخرجات التنفيذ.

تأشير المهمة إقرار منك بإتمامها، وليس تصحيحًا آليًا للكود. يُحفظ تقدمك في حسابك.

مساحة التحدي

اختبر فهمك.
ووصلها للإتقان.

كل سؤال خطوة لقدّام. اختار، اكتب كود، وشوف نتيجتك فورًا.

8أسئلة 3أنواع تحديات 100%هدف الإتقان
تصحيح تلقائي. فرص بلا حدود.

أكمل المهام، واجمع كل الإجابات الصحيحة. أقل من 100%؟ راجع وأعد المحاولة.

الأسئلة متاحة للاطلاع. سجّل الدخول للتفاعل وحفظ تقدمك.

لمحة عن التحدي8 أسئلة تنتظرك
01

ما الهدف الهندسي الأساسي من التحميل الكسول ومشكلة استعلامات N1 في إطار العمل Laravel 12؟

يسهم التحميل الكسول ومشكلة استعلامات N1 في تنظيم منطق التطبيق بأسلوب معياري آمن وقابل للصيانة في Laravel 12.

02

يساعد الالتزام باصطلاحات Laravel 12 الرسمية في قسم «التحميل المسبق للعلاقات بدالة With» على رفع جودة الكود وسهولة اختباره آلياً.

صواب؛ الالتزام بالمعايير القياسية في Laravel 12 يجعل الكود واضحاً وسهل الفحص والصيانة.

03

أي آلية في Laravel 12 تتولى إدارة التحميل المتداخل وتحديد الأعمدة بشكل مباشر ومنظم؟

توفر طبقة إطار العمل وحاوية الخدمات في Laravel 12 الأدوات القياسية لإدارة التحميل المتداخل وتحديد الأعمدة.

04

لماذا يُعد تطبيق تقييد التحميل المسبق ودالة Load مهماً عند بناء تطبيقات Laravel 12 جاهزة للإنتاج؟

لأنه يمنع الأخطاء البرمجية الخفية ويوحد سلوك التطبيق بين بيئتي التطوير والإنتاج.

05

في Laravel 12، يُنصح بكتابة مفاتيح الإنتاج السرية مباشرة داخل ملفات الكود المصدري المرفوعة إلى Git بدلاً من ملفات البيئة.

خطأ؛ يجب حفظ المفاتيح والبيانات السرية في متغيرات البيئة وعدم رفعها أبداً إلى مستودع Git.

06

ما المزايا الهندسية التي يحققها تطبيق منع التحميل الكسول أثناء التطوير في Laravel 12؟ (اختر كل ما ينطبق)

يوفر فصلاً واضحاً للمسؤوليات، وأماناً أعلى أثناء التنفيذ، وتعاوناً أسهل بين أفراد الفريق.

07

يوظف إطار العمل Laravel 12 ميزات PHP 8 الحديثة مثل تحديد أنواع القيم المرجعة لجعل الكود أكثر وضوحاً وأماناً.

صواب؛ يعتمد Laravel 12 بشكل كامل على الصياغة الحديثة للغة PHP 8.2+ وسلامة الأنواع.

08

ما الفرق الجوهري بين معيار Laravel 12 الحديث والملفات اليدوية التقليدية في ملخص التحميل المسبق والأداء؟

يوفر Laravel 12 واجهات قياسية موحدة وحماية مدمجة تغني عن الكود اليدوي المعرض للأخطاء.