كيفية بناء WHERE معقد في Laravel Eloquent: 4 طرق مع أمثلة

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

كيفية بناء WHERE معقد في Laravel Eloquent: 4 طرق مع أمثلة

\n\n

تخيل: أنت تبني متجرًا إلكترونيًا باستخدام Laravel. تحتاج إلى العثور على جميع المنتجات التي تتراوح أسعارها بين 1000 و 5000 ريال، متوفرة في المخزون، ولكن ليست من قسم "التخفيضات"، و تم إنشاؤها بعد 1 يناير 2024. كيف تفعل ذلك باستعلام واحد دون التأثير على الأداء؟

\n\n

هذا السؤال هو من أكثر الأسئلة شيوعًا على Stack Overflow (آلاف المشاهدات!). وليس من دون سبب: القدرة على بناء شروط WHERE معقدة في Laravel Eloquent تفرّق بين المبتدئ والمطور المحترف.

\n\n

في هذه المقالة، سأعرض لكم 4 طرق مجربة لإنشاء شروط WHERE متعددة. ستتعلم متى تستخدم المصفوفات، ومتى تستخدم closures، وكيفية تجميع الشروط، وكيفية تجنب هجمات SQL injection. هيا بنا!

\n\n
\n\n

1. الطريقة الأساسية: مصفوفة الشروط (لـ AND البسيط)

\n\n

أبسط حالة هي عندما تكون جميع الشروط متصلة عبر AND. يتيح لك Laravel تمرير مصفوفة عادية إلى where():

\n\n
<?php\n\n// نريد العثور على المستخدمين النشطين من السعودية، الذين تم إنشاؤهم في 2024\n$users = User::where([\n    ['status', '=', 'active'],\n    ['country', '=', 'Saudi Arabia'],\n    ['created_at', '>=', '2024-01-01'],\n])->get();\n\n// SQL: SELECT * FROM users WHERE status = 'active' AND country = 'Saudi Arabia' AND created_at >= '2024-01-01'
\n\n

متى تستخدم: عندما يكون لديك 2-5 شروط بسيطة مع عامل = أو >. الكود يصبح مقروءًا، لكنه ليس مرنًا.

\n\n

العيب: إذا كنت بحاجة إلى خلط AND و OR، فإن المصفوفة لا تفي بالغرض.

\n\n

2. سلسلة دوال where() (للشروط الديناميكية)

\n\n

هذه هي الطريقة الأكثر شيوعًا بين المطورين. يمكنك ببساطة استدعاء where() عدة مرات متتالية:

\n\n
<?php\n\n$products = Product::where('price', '>', 1000)\n    ->where('price', '<', 5000)\n    ->where('in_stock', true)\n    ->where('category_id', '!=', 5)\n    ->get();\n\n// SQL: ... WHERE price > 1000 AND price < 5000 AND in_stock = 1 AND category_id <> 5
\n\n

خدعة: يمكنك دمجها مع شروط أخرى:

\n\n
<?php\n\n// شرط "أو" داخل السلسلة\n$orders = Order::where('status', 'paid')\n    ->orWhere('status', 'shipped')\n    ->where('total', '>', 100)  // انتبه: هذا الشرط يُطبق على orWhere السابق!\n    ->get();\n\n// SQL: ... WHERE status = 'paid' OR (status = 'shipped' AND total > 100)
\n\n

⚠️ مهم! في المثال الأخير، حيث total > 100 يُطبق فقط على status = 'shipped'. إذا كنت تريد أن يكون كلا الحالتين مع total > 100، اقرأ النقطة التالية.

\n\n

3. تجميع الشروط عبر closures (AND + OR معًا)

\n\n

هنا نصل إلى أقوى أداة. عندما تحتاج إلى إنشاء مجموعة من الشروط بين قوسين، استخدم closure داخل where():

\n\n
<?php\n\n// المهمة: العثور على الطلبات بحالة "مدفوع" أو "تم الشحن"،\n// ولكن يجب أن يكون total > 100 في كلتا الحالتين\n$orders = Order::where(function($query) {\n        $query->where('status', 'paid')\n              ->orWhere('status', 'shipped');\n    })\n    ->where('total', '>', 100)\n    ->get();\n\n// SQL: ... WHERE (status = 'paid' OR status = 'shipped') AND total > 100
\n\n

الآن تم تجميع الشروط بشكل صحيح! يمكنك تداخل closures داخل بعضها البعض بقدر ما تريد:

\n\n
<?php\n\n// فلتر معقد للتحليلات\n$data = Sale::where('date', '>=', '2024-01-01')\n    ->where(function($q) {\n        $q->where('amount', '>', 10000)\n          ->orWhere('is_vip', true);\n    })\n    ->where(function($q) {\n        $q->where('region', 'Riyadh')\n          ->orWhere('region', 'Jeddah');\n    })\n    ->get();\n\n// SQL: ... WHERE date >= '2024-01-01' AND (amount > 10000 OR is_vip = 1) AND (region = 'Riyadh' OR region = 'Jeddah')
\n\n

4. whereHas: الشروط على العلاقات (المتقدم)

\n\n

أحيانًا تحتاج إلى تصفية بناءً على بيانات من جدول مرتبط. هنا يأتي دور whereHas:

\n\n
<?php\n\n// العثور على المستخدمين الذين لديهم طلبات بقيمة إجمالية تزيد عن 5000\n$users = User::whereHas('orders', function($query) {\n    $query->where('total', '>', 5000);\n})->get();\n\n// SQL: SELECT * FROM users WHERE EXISTS (SELECT 1 FROM orders WHERE orders.user_id = users.id AND total > 5000)
\n\n

مثال متقدم: ابحث عن المنتجات التي لها تعليقات من مستخدمين نشطين:

\n\n
<?php\n\n$products = Product::whereHas('reviews', function($query) {\n    $query->whereHas('user', function($q) {\n        $q->where('status', 'active');\n    });\n})->get();
\n\n

نصائح إضافية للأداء والأمان

\n\n
    \n
  • استخدم whereIn بدلاً من orWhere المتكرر: بدلاً من orWhere('status', 'a')->orWhere('status', 'b')، استخدم whereIn('status', ['a', 'b']).
  • \n
  • تجنب N+1: عند استخدام whereHas، فكر في استخدام with() لتحميل العلاقات مسبقًا.
  • \n
  • الحماية من SQL injection: استخدم دائمًا parameter binding (كما في الأمثلة أعلاه). لا تقم بتوصيل المدخلات مباشرة في الاستعلام.
  • \n
\n\n

الخلاصة

\n\n

الآن لديك 4 أدوات قوية لبناء شروط WHERE معقدة في Laravel Eloquent:

\n\n
    \n
  1. المصفوفات للشروط البسيطة AND.
  2. \n
  3. سلسلة الدوال للشروط الديناميكية.
  4. \n
  5. closures لتجميع AND و OR معًا.
  6. \n
  7. whereHas للتصفية عبر العلاقات.
  8. \n
\n\n

اختر الأداة المناسبة بناءً على احتياجك. تذكر: الكود الواضح والمقروء أفضل من الكود "الذكي" الذي يصعب فهمه. ابدأ بتطبيق هذه التقنيات في مشروعك اليوم!

المدونات

توصيات الكتب