الفرق بين المراجعتين لصفحة: «Laravel/queries»
تسنيم-ولهازي (نقاش | مساهمات) أنشأ الصفحة ب' = قواعد البيانات: منشئ الاستعلامات = == مقدمة == يوفّر منشئ استعلامات قاعدة بيانات Laravel واجهة م...' |
رؤيا-بنعطية (نقاش | مساهمات) ط استبدال النص - '\[\[تصنيف:(.*)\]\]' ب'{{SUBPAGENAME}}' |
||
(7 مراجعات متوسطة بواسطة مستخدمين اثنين آخرين غير معروضة) | |||
سطر 1: | سطر 1: | ||
<noinclude>{{DISPLAYTITLE:منشئ الاستعلامات في Laravel}}</noinclude> | |||
[[تصنيف:Laravel|{{SUBPAGENAME}}]] | |||
[[تصنيف:Laravel Database|{{SUBPAGENAME}}]] | |||
== مقدمة == | ==مقدمة== | ||
يوفّر منشئ استعلامات قاعدة بيانات Laravel واجهة ملائمة وسلسة لإنشاء وإدارة استعلامات قاعدة البيانات. يمكن استخدامه لتنفيذ معظم عمليات قاعدة البيانات بتطبيقك كما أنه يعمل على جميع أنظمة قواعد البيانات المدعومة. | يوفّر منشئ استعلامات قاعدة بيانات Laravel واجهة ملائمة وسلسة لإنشاء وإدارة استعلامات قاعدة البيانات. يمكن استخدامه لتنفيذ معظم عمليات قاعدة البيانات بتطبيقك كما أنه يعمل على جميع أنظمة قواعد البيانات المدعومة. | ||
يستخدم منشئ استعلامات Laravel ارتباط المعاملة PDO لحماية تطبيقك من هجمات حقن SQL. لا حاجة لتنظيف السلاسل النصيّة التي تُمرّر كارتباطات. | يستخدم منشئ استعلامات Laravel ارتباط المعاملة PDO لحماية تطبيقك من هجمات حقن SQL. لا حاجة لتنظيف السلاسل النصيّة التي تُمرّر كارتباطات. | ||
==استرداد النتائج== | |||
== استرداد النتائج == | ===استرداد جميع الصفوف من الجدول=== | ||
تستطيع استخدام التابع <code>table</code> على الواجهة الساكنة <code>DB</code> لبدء استعلام. يرد التابع <code>table</code> نسخة منشئ استعلامات فصيحة (fluent) للجدول المحدد، ممّا يسمح لك بربط المزيد من القيود بالاستعلام ثم الحصول على النتائج في النهاية باستخدام التابع <code>get</code>:<syntaxhighlight lang="php"> | تستطيع استخدام التابع <code>table</code> على الواجهة الساكنة <code>DB</code> لبدء استعلام. يرد التابع <code>table</code> نسخة منشئ استعلامات فصيحة (fluent) للجدول المحدد، ممّا يسمح لك بربط المزيد من القيود بالاستعلام ثم الحصول على النتائج في النهاية باستخدام التابع <code>get</code>:<syntaxhighlight lang="php"> | ||
<?php | <?php | ||
سطر 40: | سطر 37: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
===استرداد صف أو عمود مفرد من جدول=== | |||
تستطيع استخدام التابع <code>first</code> إن احتجت لاسترداد صف واحد فقط من جدول قاعدة البيانات. سيعيد هذا التابع كائن <code>StdClass</code> واحد:<syntaxhighlight lang="php"> | تستطيع استخدام التابع <code>first</code> إن احتجت لاسترداد صف واحد فقط من جدول قاعدة البيانات. سيعيد هذا التابع كائن <code>StdClass</code> واحد:<syntaxhighlight lang="php"> | ||
$user = DB::table('users')->where('name', 'John')->first(); | $user = DB::table('users')->where('name', 'John')->first(); | ||
سطر 51: | سطر 47: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
===استرداد قائمة قيم الأعمدة=== | |||
تستطيع استخدام التابع <code>pluck</code> إن رغبت في استرداد مجموعة تحتوي على قيم عمود واحد. سنسترد في هذا المثال، مجموعة من عناوين الوظائف (roles):<syntaxhighlight lang="php"> | تستطيع استخدام التابع <code>pluck</code> إن رغبت في استرداد مجموعة تحتوي على قيم عمود واحد. سنسترد في هذا المثال، مجموعة من عناوين الوظائف (roles):<syntaxhighlight lang="php"> | ||
$titles = DB::table('roles')->pluck('title'); | $titles = DB::table('roles')->pluck('title'); | ||
سطر 68: | سطر 63: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
===تقسيم النتائج (Chunking Results)=== | |||
=== تقسيم النتائج (Chunking Results) === | |||
من المُقترح استخدام التابع <code>chunk</code> إن إحتجت للعمل مع الآلاف من سجلات قاعدة البيانات. يعيد هذا التابع جزءًا صغيرًا من النتائج كل مرّة ويعطي كل قطعة لنطاق مغلق Closure للمعالجة. هذا التابع مفيد جدًا في كتابة الأوامر Artisan التي تعالج آلاف السجلات. دعنا نعمل مثلًا مع الجدول users كاملًا لكن على أجزاء من 100 سجل في كل مرّة:<syntaxhighlight lang="php"> | من المُقترح استخدام التابع <code>chunk</code> إن إحتجت للعمل مع الآلاف من سجلات قاعدة البيانات. يعيد هذا التابع جزءًا صغيرًا من النتائج كل مرّة ويعطي كل قطعة لنطاق مغلق Closure للمعالجة. هذا التابع مفيد جدًا في كتابة الأوامر Artisan التي تعالج آلاف السجلات. دعنا نعمل مثلًا مع الجدول users كاملًا لكن على أجزاء من 100 سجل في كل مرّة:<syntaxhighlight lang="php"> | ||
DB::table('users')->orderBy('id')->chunk(100, function ($users) { | DB::table('users')->orderBy('id')->chunk(100, function ($users) { | ||
سطر 84: | سطر 78: | ||
}); | }); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
===المجاميع=== | |||
=== المجاميع === | |||
يوفّر منشئ الاستعلامات أيضًا مجموعة متنوعة من التوابع التجميعية (aggregate methods) مثل <code>count</code>، و <code>max</code>، و <code>min</code>، و <code>avg</code>، و <code>sum</code>. تستطيع مناداة أي من هذه التوابع بعد إنشاء استعلامك:<syntaxhighlight lang="php"> | يوفّر منشئ الاستعلامات أيضًا مجموعة متنوعة من التوابع التجميعية (aggregate methods) مثل <code>count</code>، و <code>max</code>، و <code>min</code>، و <code>avg</code>، و <code>sum</code>. تستطيع مناداة أي من هذه التوابع بعد إنشاء استعلامك:<syntaxhighlight lang="php"> | ||
$users = DB::table('users')->count(); | $users = DB::table('users')->count(); | ||
سطر 96: | سطر 89: | ||
->avg('price'); | ->avg('price'); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
====تحديد ما إذا كانت السجلات موجودة==== | |||
==== تحديد ما إذا كانت السجلات موجودة ==== | |||
تستطيع استخدام الأساليب <code>exists</code> و <code>doesntExist</code> بدل استخدام التابع <code>count</code> لتحديد ما إذا طابقت أية سجلات قيود استعلامك:<syntaxhighlight lang="php"> | تستطيع استخدام الأساليب <code>exists</code> و <code>doesntExist</code> بدل استخدام التابع <code>count</code> لتحديد ما إذا طابقت أية سجلات قيود استعلامك:<syntaxhighlight lang="php"> | ||
return DB::table('orders')->where('finalized', 1)->exists(); | return DB::table('orders')->where('finalized', 1)->exists(); | ||
سطر 103: | سطر 95: | ||
return DB::table('orders')->where('finalized', 1)->doesntExist(); | return DB::table('orders')->where('finalized', 1)->doesntExist(); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==معاملات عرض السجلّات Selects== | |||
===تحديد بند <code>Select</code>=== | |||
قد لا ترغب دائمًا طبعًا في تحديد (select) كافة الأعمدة من جدول قاعدة البيانات. تستطيع تحديد بند select مُخصّص للاستعلام باستخدام التابع <code>select</code>:<syntaxhighlight lang="php"> | |||
$users = DB::table('users')->select('name', 'email as user_email')->get(); | |||
</syntaxhighlight>يسمح لك التابع <code>distinct</code> باجبار الاستعلام على ردّ النتائج الفريدة:<syntaxhighlight lang="php"> | |||
$users = DB::table('users')->distinct()->get(); | |||
</syntaxhighlight>تستطيع استخدام التابع <code>addSelect</code> إن كان لديك نسخة منشئ استعلامات مسبقًا ورغبت في إضافة عمود آخر لعموده Select الحالي:<syntaxhighlight lang="php"> | |||
$query = DB::table('users')->select('name'); | |||
$users = $query->addSelect('age')->get(); | |||
</syntaxhighlight> | |||
==تعبيرات خام== | |||
قد تحتاج في بعض الأحيان لاستخدام تعبير خام في استعلام. تستطيع استخدام التابع <code>DB::raw</code> لإنشاء تعبير خام:<syntaxhighlight lang="php"> | |||
$users = DB::table('users') | |||
->select(DB::raw('count(*) as user_count, status')) | |||
->where('status', '<>', 1) | |||
->groupBy('status') | |||
->get(); | |||
</syntaxhighlight>ملاحظة: ستُضاف التعابير الخامة للاستعلام كسلاسل نصيّة لذا عليك التزام الحذر الشديد كيلا تخلق نقاط ضعف حُقن SQL. | |||
===التوابع الخامة=== | |||
تستطيع أيضًا استخدام التوابع التالية بدلاً من استخدام <code>DB::raw</code> لإدراج تعبير خام في أجزاء مختلفة من استعلامك. | |||
====<code>selectRaw</code>==== | |||
يمكن استخدام التابع <code>selectRaw</code> بدلاً من <code>select(DB::raw(...))</code>. يقبل هذا التابع مصفوفةً اختياريّةً من الارتباطات كمتغيّر وسيط ثاني لها:<syntaxhighlight lang="php"> | |||
$orders = DB::table('orders') | |||
->selectRaw('price * ? as price_with_tax', [1.0825]) | |||
->get(); | |||
</syntaxhighlight> | |||
====<code>whereRaw</code> / <code>orWhereRaw</code>==== | |||
<code>whereRaw</code> و <code>orWhereRaw</code> هما تابعان يمكن استخدامها لإضافة بند <code>where</code> خام لاستعلامك. تقبل هذه التوابع مصفوفة اختياريّة من الارتباطات كمتغيّر وسيط ثاني لها:<syntaxhighlight lang="php"> | |||
$orders = DB::table('orders') | |||
->whereRaw('price > IF(state = "TX", ?, 100)', [200]) | |||
->get(); | |||
</syntaxhighlight> | |||
====<code>havingRaw</code> / <code>orHavingRaw</code>==== | |||
<code>havingRaw</code> و <code>orHavingRaw</code> هما تابعان يمكن استخدامها لتعيين سلسلة نصيّة خام كقيمة البند having. تقبل هذه التوابع مصفوفة اختيارية من الارتباطات كمتغيّر وسيط ثاني لها:<syntaxhighlight lang="php"> | |||
$orders = DB::table('orders') | |||
->select('department', DB::raw('SUM(price) as total_sales')) | |||
->groupBy('department') | |||
->havingRaw('SUM(price) > ?', [2500]) | |||
->get(); | |||
</syntaxhighlight> | |||
====<code>orderByRaw</code>==== | |||
يمكن استخدام التابع <code>orderByRaw</code> لتعيين سلسلة نصيّة خامة كقيمة البند order by:<syntaxhighlight lang="php"> | |||
$orders = DB::table('orders') | |||
->orderByRaw('updated_at - created_at DESC') | |||
->get(); | |||
</syntaxhighlight> | |||
==معاملات ربط الجداول Joins== | |||
===بند الربط الداخلي (Inner Join Clause)=== | |||
يمكن استخدام منشئ الاستعلامات لكتابة تعابير الربط (join statements). لإجراء "ربط داخلي" بسيط، تستطيع استخدام التابع <code>join</code> على نسخة منشئ استعلامات. أوّل متغيّر وسيط يُمرّر إلى التابع <code>join</code> هو اسم الجدول الذي تحتاج للربط به في حين أن المُغيّرات الباقية تحدد قيود العمود للربط. تستطيع كما ترى الربط بعدّة جداول في استعلام واحد:<syntaxhighlight lang="php"> | |||
$users = DB::table('users') | |||
->join('contacts', 'users.id', '=', 'contacts.user_id') | |||
->join('orders', 'users.id', '=', 'orders.user_id') | |||
->select('users.*', 'contacts.phone', 'orders.price') | |||
->get(); | |||
</syntaxhighlight> | |||
===بند الربط اليساري (Left Join Clause)=== | |||
إن رغبت في عمل "ربط يساري" بدلاً من "ربط داخلي"، استخدم التابع <code>leftJoin</code>. يملك التابع <code>leftJoin</code> نفس توقيع التابع <code>join</code>:<syntaxhighlight lang="php"> | |||
$users = DB::table('users') | |||
->leftJoin('posts', 'users.id', '=', 'posts.user_id') | |||
->get(); | |||
</syntaxhighlight> | |||
===بند الربط المُتقاطع (Cross Join Clause)=== | |||
لعمل "ربط مُتقاطع"، استخدم التابع <code>crossJoin</code> مع اسم الجدول الذي ترغب في الربط به. يولّد الربط المُتقاطع نتيجة ديكارتيّة بين الجدول الأول والجدول المربوط:<syntaxhighlight lang="php"> | |||
$users = DB::table('sizes') | |||
->crossJoin('colours') | |||
->get(); | |||
</syntaxhighlight> | |||
===بنود الربط المتقدّمة=== | |||
تستطيع أيضًا تحديد شروط ربط أكثر تقّدمًا. للبدء، مرّر Closure كالمتغيّر الوسيط الثاني في التابع <code>join</code>. سيتلقّى Closure كائن <code>JoinClause</code> والذي يسمح لك بتحديد القيود على البند <code>join</code>:<syntaxhighlight lang="php"> | |||
DB::table('users') | |||
->join('contacts', function ($join) { | |||
$join->on('users.id', '=', 'contacts.user_id')->orOn(...); | |||
}) | |||
->get(); | |||
</syntaxhighlight>تستطيع استخدام التابعين <code>where</code> و <code>orWhere</code> في الربط إن رغبت في استخدام شرط على نمط "where" في ارتباطاتك (joins). ستُقارن هذه التوابع العمود بالقيمة بدلاً من مقارنة عمودين ببعضهما:<syntaxhighlight lang="php"> | |||
DB::table('users') | |||
->join('contacts', function ($join) { | |||
$join->on('users.id', '=', 'contacts.user_id') | |||
->where('contacts.user_id', '>', 5); | |||
}) | |||
->get(); | |||
</syntaxhighlight> | |||
===ربط الاستعلام الفرعي ( Sub-Query Joins)=== | |||
تستطيع استخدام التوابع <code>joinSub</code> <code>leftJoinSub</code> و <code>rightJoinSub</code> و <code>rightJoinSub</code> لربط استعلام باستعلام فرعي. يتلقى كل تابع من هذه التوابع ثلاث مُتغيّرات وسيطة: الاستعلام الفرعي، واسم جدولها المستعار (table alias)، ونطاق مغلق يحدّد الأعمدة ذات الصلة:<syntaxhighlight lang="php"> | |||
$latestPosts = DB::table('posts') | |||
->select('user_id', DB::raw('MAX(created_at) as last_post_created_at')) | |||
->where('is_published', true) | |||
->groupBy('user_id'); | |||
$users = DB::table('users') | |||
->joinSub($latestPosts, 'latest_posts', function($join) { | |||
$join->on('users.id', '=', 'latest_posts.user_id'); | |||
})->get(); | |||
</syntaxhighlight> | |||
== معاملات الدمج Unions == | |||
يُوفّر منشئ الاستعلامات أيضًا طريقة سريعة "لدمج" استعلامين معًا. تستطيع مثلًا إنشاء استعلام الأولي ثم استخدام التابع <code>union</code> لدمجه باستعلام الثاني:<syntaxhighlight lang="php"> | |||
$first = DB::table('users') | |||
->whereNull('first_name'); | |||
$users = DB::table('users') | |||
->whereNull('last_name') | |||
->union($first) | |||
->get(); | |||
</syntaxhighlight>ملاحظة: يوجد أيضًا التابع <code>unionAll</code> وله نفس إمضاء التابع <code>union</code>. | |||
== البنود Where == | |||
=== بنود <code>Where</code> البسيطة === | |||
تستطيع استخدام التابع <code>where</code> على نسخة منشئ استعلامات لإضافة بنود <code>where</code> للاستعلام. يتطلب أبسط نداء <code>where</code> ثلاث وسائط. المتغيّر الوسيط الأول هو اسم العمود. المتغيّر الوسيط الثاني هو المُعامل (operator)، والذي يمكن أن يكون أي من المُعاملين المعتمدين في قاعدة البيانات. وأخيرًا يكون المتغيّر الوسيط الثالث هو القيمة التي تُقيّم حسب العمود. | |||
تجد هنا مثلًا استعلامًا يتحقّق من مساواة قيمة العمود "votes" للعدد 100:<syntaxhighlight lang="php"> | |||
$users = DB::table('users')->where('votes', '=', 100)->get(); | |||
</syntaxhighlight>إن أردت التحقّق من مساواة عمود ما لقيمة معيّنة تستطيع ببساطة تمرير القيمة مباشرة كالمُتغيّر الثاني بالتابع <code>where</code>:<syntaxhighlight lang="php"> | |||
$users = DB::table('users')->where('votes', 100)->get(); | |||
</syntaxhighlight>تستطيع طبعًا استخدام عدّة مُعاملين آخرين عند كتابة الشرط where:<syntaxhighlight lang="php"> | |||
$users = DB::table('users') | |||
->where('votes', '>=', 100) | |||
->get(); | |||
$users = DB::table('users') | |||
->where('votes', '<>', 100) | |||
->get(); | |||
$users = DB::table('users') | |||
->where('name', 'like', 'T%') | |||
->get(); | |||
</syntaxhighlight>تستطيع أيضًا تمرير مصفوفة من الشروط للتابع <code>where</code>:<syntaxhighlight lang="php"> | |||
$users = DB::table('users')->where([ | |||
['status', '=', '1'], | |||
['subscribed', '<>', '1'], | |||
])->get(); | |||
</syntaxhighlight> | |||
=== العبارات <code>Or</code> === | |||
تستطيع ربط قيود <code>where</code> معًا كما تستطيع إضافةً بنود <code>or</code> للاستعلام. يقبل التابع <code>orWhere</code> نفس المُتغيّرات الوسيطة كالتابع <code>where</code>:<syntaxhighlight lang="php"> | |||
$users = DB::table('users') | |||
->where('votes', '>', 100) | |||
->orWhere('name', 'John') | |||
->get(); | |||
</syntaxhighlight> | |||
=== بنود <code>Where</code> إضاقيّة === | |||
==== <code>whereBetween</code> ==== | |||
يتحقّق التابع من كون قيمة العمود بين قيمتين:<syntaxhighlight lang="php"> | |||
$users = DB::table('users') | |||
->whereBetween('votes', [1, 100])->get(); | |||
</syntaxhighlight> | |||
==== <code>whereNotBetween</code> ==== | |||
يتحقّق التابع من كون قيمة العمود خارج قيمتين:<syntaxhighlight lang="php"> | |||
$users = DB::table('users') | |||
->whereNotBetween('votes', [1, 100]) | |||
->get(); | |||
</syntaxhighlight> | |||
==== <code>whereIn</code> / <code>whereNotIn</code> ==== | |||
يتحقق التابع <code>whereIn</code> من وجود قيمة العمود المحدّد داخل المصفوفة المحدّدة:<syntaxhighlight lang="php"> | |||
$users = DB::table('users') | |||
->whereIn('id', [1, 2, 3]) | |||
->get(); | |||
</syntaxhighlight>يتحقق التابع <code>whereNotIn</code> من عدم وجود قيمة العمود المحدّد داخل المصفوفة المحدّدة:<syntaxhighlight lang="php"> | |||
$users = DB::table('users') | |||
->whereNotIn('id', [1, 2, 3]) | |||
->get(); | |||
</syntaxhighlight> | |||
==== <code>whereNull</code> / <code>whereNotNull</code> ==== | |||
يتحقق التابع <code>whereNull</code> من كون قيمة العمود المحدّدة <code>NULL</code>:<syntaxhighlight lang="php"> | |||
$users = DB::table('users') | |||
->whereNull('updated_at') | |||
->get(); | |||
</syntaxhighlight>يتحقق التابع <code>whereNotNull</code> من عدم كون قيمة العمود المحدّدة <code>NULL</code>:<syntaxhighlight lang="php"> | |||
$users = DB::table('users') | |||
->whereNotNull('updated_at') | |||
->get(); | |||
</syntaxhighlight> | |||
==== <code>whereDate</code> / <code>whereMonth</code> / <code>whereDay</code> / <code>whereYear</code> / <code>whereTime</code> ==== | |||
يمكن استخدام التابع <code>whereDate</code> لمقارنة قيمة العمود بتاريخ ما:<syntaxhighlight lang="php"> | |||
$users = DB::table('users') | |||
->whereDate('created_at', '2016-12-31') | |||
->get(); | |||
</syntaxhighlight>يمكن استخدام التابع <code>whereMonth</code> لمقارنة قيمة العمود بشهر مُعيّن من السنة:<syntaxhighlight lang="php"> | |||
$users = DB::table('users') | |||
->whereMonth('created_at', '12') | |||
->get(); | |||
</syntaxhighlight>يمكن استخدام التابع <code>whereDay</code> لمقارنة قيمة العمود بيوم معيّن من الشهر:<syntaxhighlight lang="php"> | |||
$users = DB::table('users') | |||
->whereDay('created_at', '31') | |||
->get(); | |||
</syntaxhighlight>يمكن استخدام التابع <code>whereTime</code> لمقارنة قيمة العمود بتوقيت معيّن:<syntaxhighlight lang="php"> | |||
$users = DB::table('users') | |||
->whereTime('created_at', '=', '11:20:45') | |||
->get(); | |||
</syntaxhighlight> | |||
==== <code>whereColumn</code> ==== | |||
يمكن استخدام التابع <code>whereColumn</code> للتحقق من تساوي عمودين:<syntaxhighlight lang="php"> | |||
$users = DB::table('users') | |||
->whereColumn('first_name', 'last_name') | |||
->get(); | |||
</syntaxhighlight>تستطيع أيضًا تمرير عامل مقارنة (comparison operator) للتابع:<syntaxhighlight lang="php"> | |||
users = DB::table('users') | |||
->whereColumn('updated_at', '>', 'created_at') | |||
->get(); | |||
</syntaxhighlight>يمكن أيضاً تمرير مصفوفة من عدّة شروط للتابع <code>whereColumn</code>. ستُضمّ هذه الشروط باستخدام المعامل and:<syntaxhighlight lang="php"> | |||
$users = DB::table('users') | |||
->whereColumn([ | |||
['first_name', '=', 'last_name'], | |||
['updated_at', '>', 'created_at'] | |||
])->get(); | |||
</syntaxhighlight> | |||
=== تجميع المعاملات (Parameter Grouping) === | |||
قد تحتاج أحياناً لإنشاء بنود <code>where</code> متطوّرة أكثر حيث توجد عبارات مثل "where exists" أو معاملات تجميع متداخلة (nested parameter groupings). يستطيع منشئ الاستعلامات Laravel التعامل معها أيضًا. دعنا نلق نظرة على مثال على قيود التجميع بين قوسين للبدء:<syntaxhighlight lang="php"> | |||
DB::table('users') | |||
->where('name', '=', 'John') | |||
->where(function ($query) { | |||
$query->where('votes', '>', 100) | |||
->orWhere('title', '=', 'Admin'); | |||
}) | |||
->get(); | |||
</syntaxhighlight>يأمر تمرير Closure للتابع <code>where</code> منشئ الاستعلامات ببدء مجموعة قيود. سيتلقى Closure نسخة منشئ استعلامات تستطيع استخدامها لتحديد القيود التي يجب احتواؤها داخل مجموعة القوسين. سينتج المثال أعلاه SQL التالي:<syntaxhighlight lang="sql"> | |||
select * from users where name = 'John' and (votes > 100 or title = 'Admin') | |||
</syntaxhighlight>ملاحظة: يجب دائمًا تجميع نداءات <code>orWhere</code> تجنّبًا لحدوث سلوك غير متوقع عند تطبيق النطاقات العامة. | |||
=== البنود Where <code>Exists</code> === | |||
يسمح لك التابع <code>whereExists</code> بكتابة العبارات <code>whereexists</code> SQL. يقبل التابع <code>whereExists</code> متغيّر وسيط Closure والذي سيتلقّى نسخة منشئ الاستعلامات ممّا يسمح لك بتعريف الاستعلام الذي يجب وضعه داخل البند "exists":<syntaxhighlight lang="php"> | |||
DB::table('users') | |||
->whereExists(function ($query) { | |||
$query->select(DB::raw(1)) | |||
->from('orders') | |||
->whereRaw('orders.user_id = users.id'); | |||
}) | |||
->get(); | |||
</syntaxhighlight>سينتج الاستعلام أعلاه SQL التالي:<syntaxhighlight lang="sql"> | |||
select * from users | |||
where exists ( | |||
select 1 from orders where orders.user_id = users.id | |||
) | |||
</syntaxhighlight> | |||
=== البنود JSON Where === | |||
يدعم Laravel أيضًا الاستعلام عن أنواع الأعمدة JSON بقواعد البيانات التي تدعم أنواع الأعمدة JSON. يتضمّن هذا حاليًّا MySQL 5.7 و PostgreSQL و SQL Server 2016 و SQLite 3.9.0 (مع ملحق JSON1). للاستعلام عن عمود JSON ، استخدم عامل التشغيل <code>-></code>:<syntaxhighlight lang="php"> | |||
$users = DB::table('users') | |||
->where('options->language', 'en') | |||
->get(); | |||
$users = DB::table('users') | |||
->where('preferences->dining->meal', 'salad') | |||
->get(); | |||
</syntaxhighlight>يدعم [[MySQL]] و [[PostgreSQL]] عدّة قيم من <code>whereJsonContains</code>:<syntaxhighlight lang="php"> | |||
$users = DB::table('users') | |||
->whereJsonContains('options->languages', ['en', 'de']) | |||
->get(); | |||
</syntaxhighlight> | |||
== الترتيب والتجميع والحد والإزاحة == | |||
=== <code>orderBy</code> === | |||
يتيح لك التابع فرز نتائج الاستعلام حسب عمود محدّد. يجب أن يكون متغيّر التابع <code>orderBy</code> الوسيط الأول هو العمود الذي تريد الفرز حسبه بينما يتحكّم المتغيّر الوسيط الثاني في اتجاه الفرز وقد تكون إمّا <code>asc</code> أو <code>desc</code>:<syntaxhighlight lang="php"> | |||
$users = DB::table('users') | |||
->orderBy('name', 'desc') | |||
->get(); | |||
</syntaxhighlight> | |||
=== <code>latest</code> / <code>oldest</code> === | |||
يسمح لك التابعان بترتيب النتائج حسب التاريخ بسهولة. تُرتّب النتيجة افتراضيًّا حسب العمود <code>created_at</code>. أو تستطيع تمرير اسم العمود الذي تريد الترتيب وفقًا له:<syntaxhighlight lang="php"> | |||
$user = DB::table('users') | |||
->latest() | |||
->first(); | |||
</syntaxhighlight> | |||
=== <code>inRandomOrder</code> === | |||
يُمكن استخدام التابع لفرز نتائج الاستعلام عشوائيًّا. تستطيع مثلًا استخدام هذا التابع لجلب مستخدم عشوائي:<syntaxhighlight lang="php"> | |||
$randomUser = DB::table('users') | |||
->inRandomOrder() | |||
->first(); | |||
</syntaxhighlight> | |||
=== <code>groupBy</code> / <code>having</code> === | |||
يمكن استخدام التابعين لتجميع نتائج الاستعلام. يُشابه توقيع التابع <code>having</code> توقيع التابع <code>where</code>:<syntaxhighlight lang="php"> | |||
$users = DB::table('users') | |||
->groupBy('account_id') | |||
->having('account_id', '>', 100) | |||
->get(); | |||
</syntaxhighlight>تستطيع تمرير عدّة مُتغيّرات وسيطة للتابع <code>groupBy</code> لتجميع عدّة أعمدة:<syntaxhighlight lang="php"> | |||
$users = DB::table('users') | |||
->groupBy('first_name', 'status') | |||
->having('account_id', '>', 100) | |||
->get(); | |||
</syntaxhighlight>لمزيد من المعلومات حول عبارات <code>having</code> أكثر تطوّرًا راجع التابع <code>havingRaw</code>. | |||
=== <code>skip</code> / <code>take</code> === | |||
للحد من عدد من النتائج التي يردّها الاستعلام، أو لتخطّي عدد معيّن من النتائج في الاستعلام، تستطيع استخدام التابعين <code>skip</code> و <code>take</code>:<syntaxhighlight lang="php"> | |||
$users = DB::table('users')->skip(10)->take(5)->get(); | |||
</syntaxhighlight>تستطيع كبديل استخدام التابعين <code>limit</code> و <code>offset</code>:<syntaxhighlight lang="php"> | |||
$users = DB::table('users') | |||
->offset(10) | |||
->limit(5) | |||
->get(); | |||
</syntaxhighlight> | |||
== البنود المشروطة (Conditional Clauses) == | |||
قد ترغب أحيانًا في تطبيق بنود ما على الاستعلام فقط عندما تكون قيمة شيء آخر <code>true</code>. قد ترغب مثلًا بتطبيق عبارة <code>where</code> فقط إن كانت قيمة إدخال معيّنة موجودة في الطلب الوارد. تقدر على فعل هذا باستخدام التابع <code>when</code>:<syntaxhighlight lang="php"> | |||
$role = $request->input('role'); | |||
$users = DB::table('users') | |||
->when($role, function ($query, $role) { | |||
return $query->where('role_id', $role); | |||
}) | |||
->get(); | |||
</syntaxhighlight>يُنفّذ التابع <code>when</code> النطاق المُغلق المحدّد Closure فقط عندما تكون المعاملة الأولى true. في حالة كانت المعاملة الأولى false لن يُنفّذ النطاق المغلق Closure. | |||
== | تستطيع تمرير نطاق مُغلق Closure آخر كثالث معامل للتابع <code>when</code>. سيُنفّذ هذا النطاق المُغلق في حالة كانت المعاملة الأولى false. لتوضيح كيفيّة استخدام هذه الميزة سنستخدمها لاعداد الفرز الافتراضي لاستعلام:<syntaxhighlight lang="php"> | ||
$sortBy = null; | |||
==== | $users = DB::table('users') | ||
->when($sortBy, function ($query, $sortBy) { | |||
return $query->orderBy($sortBy); | |||
}, function ($query) { | |||
return $query->orderBy('name'); | |||
}) | |||
->get(); | |||
</syntaxhighlight> | |||
== إدخالات السجلّات للجدول Inserts == | |||
يوفّر منشئ الاستعلامات أيضا تابع <code>insert</code> لإدراج السجلّات في جدول قاعدة البيانات. يقبل التابع <code>insert</code> مصفوفةً من أسماء الأعمدة وقيمها:<syntaxhighlight lang="php"> | |||
DB::table('users')->insert( | |||
['email' => '[email protected]', 'votes' => 0] | |||
); | |||
</syntaxhighlight>تستطيع حتى إدراج عدة سجلّات في الجدول بنداء insert واحد عن طريق تمرير مصفوفة من المصفوفات. تمثّل كل مصفوفة صفًا سيُدرج في الجدول:<syntaxhighlight lang="php"> | |||
DB::table('users')->insert([ | |||
['email' => '[email protected]com', 'votes' => 0], | |||
['email' => '[email protected]', 'votes' => 0] | |||
]); | |||
</syntaxhighlight> | |||
=== المُعرّفات تلقائيّة الزيادة (Auto-Incrementing IDs) === | |||
استخدم التابعين <code>insertGetId</code> و <code>insertGetId</code> إذا احتوى الجدول على معرّف تلقائي الزيادة لإدراج سجلّ ثم استرد الُمعرّف:<syntaxhighlight lang="php"> | |||
$id = DB::table('users')->insertGetId( | |||
['email' => '[email protected]', 'votes' => 0] | |||
); | |||
</syntaxhighlight>'''ملاحظة''': عند استخدام ،PostgreSQL يتوقّع التابع <code>insertGetId</code> تسمية عمود الزيادة التلقائية باسم <code>id</code>. تستطيع تمرير اسم العمود كمعاملة ثانية للتابع <code>insertGetId</code> إن رغبت باسترداد المعرّف من "تسلسل" مختلف. | |||
== التحديثات Updates == | |||
يستطيع منشئ الاستعلامات أيضًا تحديث السجلات الموجودة باستخدام التابع <code>update</code> إضافةً لإدخال السجلات في قاعدة البيانات. يقبل التابع <code>update</code>، مثل التابع <code>insert</code>، مصفوفة من أزواج الأعمدة والقيم التي تحتوي على الأعمدة المُراد تحديثها. تستطيع تقييد استعلام update باستخدام بنود where:<syntaxhighlight lang="php"> | |||
DB::table('users') | |||
->where('id', 1) | |||
->update(['votes' => 1]); | |||
</syntaxhighlight> | |||
=== تحديث أعمدة JSON === | |||
يجب استخدام الصيغة -> عند تحديث عمود JSON للوصول للمفتاح المناسب في الكائن JSON. هذه العملية مدعومة فقط على MySQL 5.7+:<syntaxhighlight lang="php"> | |||
DB::table('users') | |||
->where('id', 1) | |||
->update(['options->enabled' => true]); | |||
</syntaxhighlight> | |||
=== الزيادة والنقصان === | |||
يوفّر منشئ الاستعلامات أيضًا توابع ملائمة لزيادة قيمة العمود المُحدّد أو انقاصها. هذا اختصار يوفّر واجهة أكثر تعبيرًا واقتضابًا مقارنة بكتابة العبارة <code>update</code> يدويًا. | |||
يقبل كلا التابعين متغيّر وسيط واحد على الأقل: العمود المُراد تعديله. قد يُمرّر متغيّر وسيط ثاني اختياريًا للتحكّم في مقدار زيادة العمود أو تنقيصه:<syntaxhighlight lang="php"> | |||
DB::table('users')->increment('votes'); | |||
DB::table('users')->increment('votes', 5); | |||
DB::table('users')->decrement('votes'); | |||
DB::table('users')->decrement('votes', 5); | |||
</syntaxhighlight>تستطيع أيضًا تحديد أعمدة إضافيّة لتحديثها أثناء العملية:<syntaxhighlight lang="php"> | |||
DB::table('users')->increment('votes', 1, ['name' => 'John']); | |||
</syntaxhighlight> | |||
== الحذف Deletes == | |||
يمكن أيضًا استخدام منشئ الاستعلامات لحذف السجلات من الجدول عبر التابع <code>delete</code>. تستطيع تقييد العبارات <code>delete</code> بإضافة بنود where قبل مناداة التابع <code>delete</code>:<syntaxhighlight lang="php"> | |||
DB::table('users')->delete(); | |||
DB::table('users')->where('votes', '>', 100)->delete(); | |||
</syntaxhighlight>تستطيع استخدام التابع <code>truncate</code> إن رغبت في اقتطاع الجدول بأكمله، ممّا سيؤدي لإزالة جميع الصفوف وإعادة المُعرّف تلقائي الزيادة للصفر:<syntaxhighlight lang="php"> | |||
DB::table('users')->truncate(); | |||
</syntaxhighlight> | |||
== «الإقفال المتشائم» (Pessimistic Locking) == | |||
ويشمل منشئ الاستعلامات أيضًا عددًا صغيرًا من الدوال لمساعدتك على "الإقفال المتشائم" بعباراتك select. تستطيع استخدام التابع <code>sharedLock</code> في الاستعلام لتشغيل العبارة باستخدام "قفل مشترك". يمنع القفل المشترك تعديل الصفوف المحدّدة حتى تنفيذ (commit) معاملتك:<syntaxhighlight lang="php"> | |||
DB::table('users')->where('votes', '>', 100)->sharedLock()->get(); | |||
</syntaxhighlight>تستطيع استخدام التابع <code>lockForUpdate</code> كبديل. يمنع قفل "للتحديث" (for update) تعديل الصفوف أو تحديدها باستخدام قفل مشترك آخر:<syntaxhighlight lang="php"> | |||
DB::table('users')->where('votes', '>', 100)->lockForUpdate()->get(); | |||
</syntaxhighlight> | </syntaxhighlight> | ||
== مصادر == | |||
* [https://laravel.com/docs/5.6/queries صفحة Database: Query Builder في توثيق Laravel الرسمي.] |
المراجعة الحالية بتاريخ 13:25، 23 أكتوبر 2018
مقدمة
يوفّر منشئ استعلامات قاعدة بيانات Laravel واجهة ملائمة وسلسة لإنشاء وإدارة استعلامات قاعدة البيانات. يمكن استخدامه لتنفيذ معظم عمليات قاعدة البيانات بتطبيقك كما أنه يعمل على جميع أنظمة قواعد البيانات المدعومة.
يستخدم منشئ استعلامات Laravel ارتباط المعاملة PDO لحماية تطبيقك من هجمات حقن SQL. لا حاجة لتنظيف السلاسل النصيّة التي تُمرّر كارتباطات.
استرداد النتائج
استرداد جميع الصفوف من الجدول
تستطيع استخدام التابع table
على الواجهة الساكنة DB
لبدء استعلام. يرد التابع table
نسخة منشئ استعلامات فصيحة (fluent) للجدول المحدد، ممّا يسمح لك بربط المزيد من القيود بالاستعلام ثم الحصول على النتائج في النهاية باستخدام التابع get
:
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
class UserController extends Controller
{
/**
* عرض قائمة كل مستخدمي التطبيق.
*
* @return Response
*/
public function index()
{
$users = DB::table('users')->get();
return view('user.index', ['users' => $users]);
}
}
يعيد التابع get
الملف Illuminate\Support\Collection
الذي يحتوي على النتائج بحيث تكون كل نتيجة نسخة من الكائن PHP StdClass
. تستطيع الوصول لقيمة كل عمود عن طريق الوصول للعمود كخاصية للكائن:
foreach ($users as $user) {
echo $user->name;
}
استرداد صف أو عمود مفرد من جدول
تستطيع استخدام التابع first
إن احتجت لاسترداد صف واحد فقط من جدول قاعدة البيانات. سيعيد هذا التابع كائن StdClass
واحد:
$user = DB::table('users')->where('name', 'John')->first();
echo $user->name;
تستطيع استخراج قيمة واحدة من سجلّ ما باستخدام التابع value
إن لم تحتج حتى لصفّ كامل. سيعيد هذا التابع قيمة العمود مباشرة:
$email = DB::table('users')->where('name', 'John')->value('email');
استرداد قائمة قيم الأعمدة
تستطيع استخدام التابع pluck
إن رغبت في استرداد مجموعة تحتوي على قيم عمود واحد. سنسترد في هذا المثال، مجموعة من عناوين الوظائف (roles):
$titles = DB::table('roles')->pluck('title');
foreach ($titles as $title) {
echo $title;
}
تستطيع أيضًا تحديد عمود مفاتيح مخصصّة للمجموعة المردودة:
$roles = DB::table('roles')->pluck('title', 'name');
foreach ($roles as $name => $title) {
echo $title;
}
تقسيم النتائج (Chunking Results)
من المُقترح استخدام التابع chunk
إن إحتجت للعمل مع الآلاف من سجلات قاعدة البيانات. يعيد هذا التابع جزءًا صغيرًا من النتائج كل مرّة ويعطي كل قطعة لنطاق مغلق Closure للمعالجة. هذا التابع مفيد جدًا في كتابة الأوامر Artisan التي تعالج آلاف السجلات. دعنا نعمل مثلًا مع الجدول users كاملًا لكن على أجزاء من 100 سجل في كل مرّة:
DB::table('users')->orderBy('id')->chunk(100, function ($users) {
foreach ($users as $user) {
//
}
});
تستطيع إيقاف معالجة قطع أخرى عبر رد القيمة false
من Closure:
DB::table('users')->orderBy('id')->chunk(100, function ($users) {
// عالج السجلات...
return false;
});
المجاميع
يوفّر منشئ الاستعلامات أيضًا مجموعة متنوعة من التوابع التجميعية (aggregate methods) مثل count
، و max
، و min
، و avg
، و sum
. تستطيع مناداة أي من هذه التوابع بعد إنشاء استعلامك:
$users = DB::table('users')->count();
$price = DB::table('orders')->max('price');
تستطيع طبعًا دمج هذه التوابع مع بنود أخرى:
$price = DB::table('orders')
->where('finalized', 1)
->avg('price');
تحديد ما إذا كانت السجلات موجودة
تستطيع استخدام الأساليب exists
و doesntExist
بدل استخدام التابع count
لتحديد ما إذا طابقت أية سجلات قيود استعلامك:
return DB::table('orders')->where('finalized', 1)->exists();
return DB::table('orders')->where('finalized', 1)->doesntExist();
معاملات عرض السجلّات Selects
تحديد بند Select
قد لا ترغب دائمًا طبعًا في تحديد (select) كافة الأعمدة من جدول قاعدة البيانات. تستطيع تحديد بند select مُخصّص للاستعلام باستخدام التابع select
:
$users = DB::table('users')->select('name', 'email as user_email')->get();
يسمح لك التابع distinct
باجبار الاستعلام على ردّ النتائج الفريدة:
$users = DB::table('users')->distinct()->get();
تستطيع استخدام التابع addSelect
إن كان لديك نسخة منشئ استعلامات مسبقًا ورغبت في إضافة عمود آخر لعموده Select الحالي:
$query = DB::table('users')->select('name');
$users = $query->addSelect('age')->get();
تعبيرات خام
قد تحتاج في بعض الأحيان لاستخدام تعبير خام في استعلام. تستطيع استخدام التابع DB::raw
لإنشاء تعبير خام:
$users = DB::table('users')
->select(DB::raw('count(*) as user_count, status'))
->where('status', '<>', 1)
->groupBy('status')
->get();
ملاحظة: ستُضاف التعابير الخامة للاستعلام كسلاسل نصيّة لذا عليك التزام الحذر الشديد كيلا تخلق نقاط ضعف حُقن SQL.
التوابع الخامة
تستطيع أيضًا استخدام التوابع التالية بدلاً من استخدام DB::raw
لإدراج تعبير خام في أجزاء مختلفة من استعلامك.
selectRaw
يمكن استخدام التابع selectRaw
بدلاً من select(DB::raw(...))
. يقبل هذا التابع مصفوفةً اختياريّةً من الارتباطات كمتغيّر وسيط ثاني لها:
$orders = DB::table('orders')
->selectRaw('price * ? as price_with_tax', [1.0825])
->get();
whereRaw
/ orWhereRaw
whereRaw
و orWhereRaw
هما تابعان يمكن استخدامها لإضافة بند where
خام لاستعلامك. تقبل هذه التوابع مصفوفة اختياريّة من الارتباطات كمتغيّر وسيط ثاني لها:
$orders = DB::table('orders')
->whereRaw('price > IF(state = "TX", ?, 100)', [200])
->get();
havingRaw
/ orHavingRaw
havingRaw
و orHavingRaw
هما تابعان يمكن استخدامها لتعيين سلسلة نصيّة خام كقيمة البند having. تقبل هذه التوابع مصفوفة اختيارية من الارتباطات كمتغيّر وسيط ثاني لها:
$orders = DB::table('orders')
->select('department', DB::raw('SUM(price) as total_sales'))
->groupBy('department')
->havingRaw('SUM(price) > ?', [2500])
->get();
orderByRaw
يمكن استخدام التابع orderByRaw
لتعيين سلسلة نصيّة خامة كقيمة البند order by:
$orders = DB::table('orders')
->orderByRaw('updated_at - created_at DESC')
->get();
معاملات ربط الجداول Joins
بند الربط الداخلي (Inner Join Clause)
يمكن استخدام منشئ الاستعلامات لكتابة تعابير الربط (join statements). لإجراء "ربط داخلي" بسيط، تستطيع استخدام التابع join
على نسخة منشئ استعلامات. أوّل متغيّر وسيط يُمرّر إلى التابع join
هو اسم الجدول الذي تحتاج للربط به في حين أن المُغيّرات الباقية تحدد قيود العمود للربط. تستطيع كما ترى الربط بعدّة جداول في استعلام واحد:
$users = DB::table('users')
->join('contacts', 'users.id', '=', 'contacts.user_id')
->join('orders', 'users.id', '=', 'orders.user_id')
->select('users.*', 'contacts.phone', 'orders.price')
->get();
بند الربط اليساري (Left Join Clause)
إن رغبت في عمل "ربط يساري" بدلاً من "ربط داخلي"، استخدم التابع leftJoin
. يملك التابع leftJoin
نفس توقيع التابع join
:
$users = DB::table('users')
->leftJoin('posts', 'users.id', '=', 'posts.user_id')
->get();
بند الربط المُتقاطع (Cross Join Clause)
لعمل "ربط مُتقاطع"، استخدم التابع crossJoin
مع اسم الجدول الذي ترغب في الربط به. يولّد الربط المُتقاطع نتيجة ديكارتيّة بين الجدول الأول والجدول المربوط:
$users = DB::table('sizes')
->crossJoin('colours')
->get();
بنود الربط المتقدّمة
تستطيع أيضًا تحديد شروط ربط أكثر تقّدمًا. للبدء، مرّر Closure كالمتغيّر الوسيط الثاني في التابع join
. سيتلقّى Closure كائن JoinClause
والذي يسمح لك بتحديد القيود على البند join
:
DB::table('users')
->join('contacts', function ($join) {
$join->on('users.id', '=', 'contacts.user_id')->orOn(...);
})
->get();
تستطيع استخدام التابعين where
و orWhere
في الربط إن رغبت في استخدام شرط على نمط "where" في ارتباطاتك (joins). ستُقارن هذه التوابع العمود بالقيمة بدلاً من مقارنة عمودين ببعضهما:
DB::table('users')
->join('contacts', function ($join) {
$join->on('users.id', '=', 'contacts.user_id')
->where('contacts.user_id', '>', 5);
})
->get();
ربط الاستعلام الفرعي ( Sub-Query Joins)
تستطيع استخدام التوابع joinSub
leftJoinSub
و rightJoinSub
و rightJoinSub
لربط استعلام باستعلام فرعي. يتلقى كل تابع من هذه التوابع ثلاث مُتغيّرات وسيطة: الاستعلام الفرعي، واسم جدولها المستعار (table alias)، ونطاق مغلق يحدّد الأعمدة ذات الصلة:
$latestPosts = DB::table('posts')
->select('user_id', DB::raw('MAX(created_at) as last_post_created_at'))
->where('is_published', true)
->groupBy('user_id');
$users = DB::table('users')
->joinSub($latestPosts, 'latest_posts', function($join) {
$join->on('users.id', '=', 'latest_posts.user_id');
})->get();
معاملات الدمج Unions
يُوفّر منشئ الاستعلامات أيضًا طريقة سريعة "لدمج" استعلامين معًا. تستطيع مثلًا إنشاء استعلام الأولي ثم استخدام التابع union
لدمجه باستعلام الثاني:
$first = DB::table('users')
->whereNull('first_name');
$users = DB::table('users')
->whereNull('last_name')
->union($first)
->get();
ملاحظة: يوجد أيضًا التابع unionAll
وله نفس إمضاء التابع union
.
البنود Where
بنود Where
البسيطة
تستطيع استخدام التابع where
على نسخة منشئ استعلامات لإضافة بنود where
للاستعلام. يتطلب أبسط نداء where
ثلاث وسائط. المتغيّر الوسيط الأول هو اسم العمود. المتغيّر الوسيط الثاني هو المُعامل (operator)، والذي يمكن أن يكون أي من المُعاملين المعتمدين في قاعدة البيانات. وأخيرًا يكون المتغيّر الوسيط الثالث هو القيمة التي تُقيّم حسب العمود.
تجد هنا مثلًا استعلامًا يتحقّق من مساواة قيمة العمود "votes" للعدد 100:
$users = DB::table('users')->where('votes', '=', 100)->get();
إن أردت التحقّق من مساواة عمود ما لقيمة معيّنة تستطيع ببساطة تمرير القيمة مباشرة كالمُتغيّر الثاني بالتابع where
:
$users = DB::table('users')->where('votes', 100)->get();
تستطيع طبعًا استخدام عدّة مُعاملين آخرين عند كتابة الشرط where:
$users = DB::table('users')
->where('votes', '>=', 100)
->get();
$users = DB::table('users')
->where('votes', '<>', 100)
->get();
$users = DB::table('users')
->where('name', 'like', 'T%')
->get();
تستطيع أيضًا تمرير مصفوفة من الشروط للتابع where
:
$users = DB::table('users')->where([
['status', '=', '1'],
['subscribed', '<>', '1'],
])->get();
العبارات Or
تستطيع ربط قيود where
معًا كما تستطيع إضافةً بنود or
للاستعلام. يقبل التابع orWhere
نفس المُتغيّرات الوسيطة كالتابع where
:
$users = DB::table('users')
->where('votes', '>', 100)
->orWhere('name', 'John')
->get();
بنود Where
إضاقيّة
whereBetween
يتحقّق التابع من كون قيمة العمود بين قيمتين:
$users = DB::table('users')
->whereBetween('votes', [1, 100])->get();
whereNotBetween
يتحقّق التابع من كون قيمة العمود خارج قيمتين:
$users = DB::table('users')
->whereNotBetween('votes', [1, 100])
->get();
whereIn
/ whereNotIn
يتحقق التابع whereIn
من وجود قيمة العمود المحدّد داخل المصفوفة المحدّدة:
$users = DB::table('users')
->whereIn('id', [1, 2, 3])
->get();
يتحقق التابع whereNotIn
من عدم وجود قيمة العمود المحدّد داخل المصفوفة المحدّدة:
$users = DB::table('users')
->whereNotIn('id', [1, 2, 3])
->get();
whereNull
/ whereNotNull
يتحقق التابع whereNull
من كون قيمة العمود المحدّدة NULL
:
$users = DB::table('users')
->whereNull('updated_at')
->get();
يتحقق التابع whereNotNull
من عدم كون قيمة العمود المحدّدة NULL
:
$users = DB::table('users')
->whereNotNull('updated_at')
->get();
whereDate
/ whereMonth
/ whereDay
/ whereYear
/ whereTime
يمكن استخدام التابع whereDate
لمقارنة قيمة العمود بتاريخ ما:
$users = DB::table('users')
->whereDate('created_at', '2016-12-31')
->get();
يمكن استخدام التابع whereMonth
لمقارنة قيمة العمود بشهر مُعيّن من السنة:
$users = DB::table('users')
->whereMonth('created_at', '12')
->get();
يمكن استخدام التابع whereDay
لمقارنة قيمة العمود بيوم معيّن من الشهر:
$users = DB::table('users')
->whereDay('created_at', '31')
->get();
يمكن استخدام التابع whereTime
لمقارنة قيمة العمود بتوقيت معيّن:
$users = DB::table('users')
->whereTime('created_at', '=', '11:20:45')
->get();
whereColumn
يمكن استخدام التابع whereColumn
للتحقق من تساوي عمودين:
$users = DB::table('users')
->whereColumn('first_name', 'last_name')
->get();
تستطيع أيضًا تمرير عامل مقارنة (comparison operator) للتابع:
users = DB::table('users')
->whereColumn('updated_at', '>', 'created_at')
->get();
يمكن أيضاً تمرير مصفوفة من عدّة شروط للتابع whereColumn
. ستُضمّ هذه الشروط باستخدام المعامل and:
$users = DB::table('users')
->whereColumn([
['first_name', '=', 'last_name'],
['updated_at', '>', 'created_at']
])->get();
تجميع المعاملات (Parameter Grouping)
قد تحتاج أحياناً لإنشاء بنود where
متطوّرة أكثر حيث توجد عبارات مثل "where exists" أو معاملات تجميع متداخلة (nested parameter groupings). يستطيع منشئ الاستعلامات Laravel التعامل معها أيضًا. دعنا نلق نظرة على مثال على قيود التجميع بين قوسين للبدء:
DB::table('users')
->where('name', '=', 'John')
->where(function ($query) {
$query->where('votes', '>', 100)
->orWhere('title', '=', 'Admin');
})
->get();
يأمر تمرير Closure للتابع where
منشئ الاستعلامات ببدء مجموعة قيود. سيتلقى Closure نسخة منشئ استعلامات تستطيع استخدامها لتحديد القيود التي يجب احتواؤها داخل مجموعة القوسين. سينتج المثال أعلاه SQL التالي:
select * from users where name = 'John' and (votes > 100 or title = 'Admin')
ملاحظة: يجب دائمًا تجميع نداءات orWhere
تجنّبًا لحدوث سلوك غير متوقع عند تطبيق النطاقات العامة.
البنود Where Exists
يسمح لك التابع whereExists
بكتابة العبارات whereexists
SQL. يقبل التابع whereExists
متغيّر وسيط Closure والذي سيتلقّى نسخة منشئ الاستعلامات ممّا يسمح لك بتعريف الاستعلام الذي يجب وضعه داخل البند "exists":
DB::table('users')
->whereExists(function ($query) {
$query->select(DB::raw(1))
->from('orders')
->whereRaw('orders.user_id = users.id');
})
->get();
سينتج الاستعلام أعلاه SQL التالي:
select * from users
where exists (
select 1 from orders where orders.user_id = users.id
)
البنود JSON Where
يدعم Laravel أيضًا الاستعلام عن أنواع الأعمدة JSON بقواعد البيانات التي تدعم أنواع الأعمدة JSON. يتضمّن هذا حاليًّا MySQL 5.7 و PostgreSQL و SQL Server 2016 و SQLite 3.9.0 (مع ملحق JSON1). للاستعلام عن عمود JSON ، استخدم عامل التشغيل ->
:
$users = DB::table('users')
->where('options->language', 'en')
->get();
$users = DB::table('users')
->where('preferences->dining->meal', 'salad')
->get();
يدعم MySQL و PostgreSQL عدّة قيم من whereJsonContains
:
$users = DB::table('users')
->whereJsonContains('options->languages', ['en', 'de'])
->get();
الترتيب والتجميع والحد والإزاحة
orderBy
يتيح لك التابع فرز نتائج الاستعلام حسب عمود محدّد. يجب أن يكون متغيّر التابع orderBy
الوسيط الأول هو العمود الذي تريد الفرز حسبه بينما يتحكّم المتغيّر الوسيط الثاني في اتجاه الفرز وقد تكون إمّا asc
أو desc
:
$users = DB::table('users')
->orderBy('name', 'desc')
->get();
latest
/ oldest
يسمح لك التابعان بترتيب النتائج حسب التاريخ بسهولة. تُرتّب النتيجة افتراضيًّا حسب العمود created_at
. أو تستطيع تمرير اسم العمود الذي تريد الترتيب وفقًا له:
$user = DB::table('users')
->latest()
->first();
inRandomOrder
يُمكن استخدام التابع لفرز نتائج الاستعلام عشوائيًّا. تستطيع مثلًا استخدام هذا التابع لجلب مستخدم عشوائي:
$randomUser = DB::table('users')
->inRandomOrder()
->first();
groupBy
/ having
يمكن استخدام التابعين لتجميع نتائج الاستعلام. يُشابه توقيع التابع having
توقيع التابع where
:
$users = DB::table('users')
->groupBy('account_id')
->having('account_id', '>', 100)
->get();
تستطيع تمرير عدّة مُتغيّرات وسيطة للتابع groupBy
لتجميع عدّة أعمدة:
$users = DB::table('users')
->groupBy('first_name', 'status')
->having('account_id', '>', 100)
->get();
لمزيد من المعلومات حول عبارات having
أكثر تطوّرًا راجع التابع havingRaw
.
skip
/ take
للحد من عدد من النتائج التي يردّها الاستعلام، أو لتخطّي عدد معيّن من النتائج في الاستعلام، تستطيع استخدام التابعين skip
و take
:
$users = DB::table('users')->skip(10)->take(5)->get();
تستطيع كبديل استخدام التابعين limit
و offset
:
$users = DB::table('users')
->offset(10)
->limit(5)
->get();
البنود المشروطة (Conditional Clauses)
قد ترغب أحيانًا في تطبيق بنود ما على الاستعلام فقط عندما تكون قيمة شيء آخر true
. قد ترغب مثلًا بتطبيق عبارة where
فقط إن كانت قيمة إدخال معيّنة موجودة في الطلب الوارد. تقدر على فعل هذا باستخدام التابع when
:
$role = $request->input('role');
$users = DB::table('users')
->when($role, function ($query, $role) {
return $query->where('role_id', $role);
})
->get();
يُنفّذ التابع when
النطاق المُغلق المحدّد Closure فقط عندما تكون المعاملة الأولى true. في حالة كانت المعاملة الأولى false لن يُنفّذ النطاق المغلق Closure.
تستطيع تمرير نطاق مُغلق Closure آخر كثالث معامل للتابع when
. سيُنفّذ هذا النطاق المُغلق في حالة كانت المعاملة الأولى false. لتوضيح كيفيّة استخدام هذه الميزة سنستخدمها لاعداد الفرز الافتراضي لاستعلام:
$sortBy = null;
$users = DB::table('users')
->when($sortBy, function ($query, $sortBy) {
return $query->orderBy($sortBy);
}, function ($query) {
return $query->orderBy('name');
})
->get();
إدخالات السجلّات للجدول Inserts
يوفّر منشئ الاستعلامات أيضا تابع insert
لإدراج السجلّات في جدول قاعدة البيانات. يقبل التابع insert
مصفوفةً من أسماء الأعمدة وقيمها:
DB::table('users')->insert(
['email' => '[email protected]', 'votes' => 0]
);
تستطيع حتى إدراج عدة سجلّات في الجدول بنداء insert واحد عن طريق تمرير مصفوفة من المصفوفات. تمثّل كل مصفوفة صفًا سيُدرج في الجدول:
DB::table('users')->insert([
['email' => '[email protected]com', 'votes' => 0],
['email' => '[email protected]', 'votes' => 0]
]);
المُعرّفات تلقائيّة الزيادة (Auto-Incrementing IDs)
استخدم التابعين insertGetId
و insertGetId
إذا احتوى الجدول على معرّف تلقائي الزيادة لإدراج سجلّ ثم استرد الُمعرّف:
$id = DB::table('users')->insertGetId(
['email' => '[email protected]', 'votes' => 0]
);
ملاحظة: عند استخدام ،PostgreSQL يتوقّع التابع insertGetId
تسمية عمود الزيادة التلقائية باسم id
. تستطيع تمرير اسم العمود كمعاملة ثانية للتابع insertGetId
إن رغبت باسترداد المعرّف من "تسلسل" مختلف.
التحديثات Updates
يستطيع منشئ الاستعلامات أيضًا تحديث السجلات الموجودة باستخدام التابع update
إضافةً لإدخال السجلات في قاعدة البيانات. يقبل التابع update
، مثل التابع insert
، مصفوفة من أزواج الأعمدة والقيم التي تحتوي على الأعمدة المُراد تحديثها. تستطيع تقييد استعلام update باستخدام بنود where:
DB::table('users')
->where('id', 1)
->update(['votes' => 1]);
تحديث أعمدة JSON
يجب استخدام الصيغة -> عند تحديث عمود JSON للوصول للمفتاح المناسب في الكائن JSON. هذه العملية مدعومة فقط على MySQL 5.7+:
DB::table('users')
->where('id', 1)
->update(['options->enabled' => true]);
الزيادة والنقصان
يوفّر منشئ الاستعلامات أيضًا توابع ملائمة لزيادة قيمة العمود المُحدّد أو انقاصها. هذا اختصار يوفّر واجهة أكثر تعبيرًا واقتضابًا مقارنة بكتابة العبارة update
يدويًا.
يقبل كلا التابعين متغيّر وسيط واحد على الأقل: العمود المُراد تعديله. قد يُمرّر متغيّر وسيط ثاني اختياريًا للتحكّم في مقدار زيادة العمود أو تنقيصه:
DB::table('users')->increment('votes');
DB::table('users')->increment('votes', 5);
DB::table('users')->decrement('votes');
DB::table('users')->decrement('votes', 5);
تستطيع أيضًا تحديد أعمدة إضافيّة لتحديثها أثناء العملية:
DB::table('users')->increment('votes', 1, ['name' => 'John']);
الحذف Deletes
يمكن أيضًا استخدام منشئ الاستعلامات لحذف السجلات من الجدول عبر التابع delete
. تستطيع تقييد العبارات delete
بإضافة بنود where قبل مناداة التابع delete
:
DB::table('users')->delete();
DB::table('users')->where('votes', '>', 100)->delete();
تستطيع استخدام التابع truncate
إن رغبت في اقتطاع الجدول بأكمله، ممّا سيؤدي لإزالة جميع الصفوف وإعادة المُعرّف تلقائي الزيادة للصفر:
DB::table('users')->truncate();
«الإقفال المتشائم» (Pessimistic Locking)
ويشمل منشئ الاستعلامات أيضًا عددًا صغيرًا من الدوال لمساعدتك على "الإقفال المتشائم" بعباراتك select. تستطيع استخدام التابع sharedLock
في الاستعلام لتشغيل العبارة باستخدام "قفل مشترك". يمنع القفل المشترك تعديل الصفوف المحدّدة حتى تنفيذ (commit) معاملتك:
DB::table('users')->where('votes', '>', 100)->sharedLock()->get();
تستطيع استخدام التابع lockForUpdate
كبديل. يمنع قفل "للتحديث" (for update) تعديل الصفوف أو تحديدها باستخدام قفل مشترك آخر:
DB::table('users')->where('votes', '>', 100)->lockForUpdate()->get();