الفرق بين المراجعتين ل"Laravel/queries"

من موسوعة حسوب
اذهب إلى التنقل اذهب إلى البحث
سطر 1: سطر 1:
  
 
<noinclude>{{DISPLAYTITLE:قواعد البيانات: منشئ الاستعلامات}}</noinclude>
 
<noinclude>{{DISPLAYTITLE:قواعد البيانات: منشئ الاستعلامات}}</noinclude>
== مقدمة ==
+
==مقدمة==
 
 
 
يوفّر منشئ استعلامات قاعدة بيانات 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
سطر 39: سطر 36:
  
 
</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();
سطر 50: سطر 46:
  
 
</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');
سطر 67: سطر 62:
  
 
</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) {
سطر 83: سطر 77:
 
});
 
});
 
</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();
سطر 95: سطر 88:
 
                 ->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();
سطر 116: سطر 108:
  
 
</syntaxhighlight>
 
</syntaxhighlight>
 
+
==تعبيرات خام==
== تعبيرات خام ==
 
 
قد تحتاج في بعض الأحيان لاستخدام تعبير خام في استعلام. تستطيع استخدام التابع <code>DB::raw</code> لإنشاء تعبير خام:<syntaxhighlight lang="php">
 
قد تحتاج في بعض الأحيان لاستخدام تعبير خام في استعلام. تستطيع استخدام التابع <code>DB::raw</code> لإنشاء تعبير خام:<syntaxhighlight lang="php">
 
$users = DB::table('users')
 
$users = DB::table('users')
سطر 125: سطر 116:
 
                     ->get();
 
                     ->get();
 
</syntaxhighlight>ملاحظة: ستُضاف التعابير الخامة للاستعلام كسلاسل نصيّة لذا عليك التزام الحذر الشديد كيلا تخلق نقاط ضعف حُقن SQL.
 
</syntaxhighlight>ملاحظة: ستُضاف التعابير الخامة للاستعلام كسلاسل نصيّة لذا عليك التزام الحذر الشديد كيلا تخلق نقاط ضعف حُقن SQL.
 
+
===التوابع الخامة===
=== التوابع الخامة ===
 
 
تستطيع أيضًا استخدام التوابع التالية بدلاً من استخدام <code>DB::raw</code> لإدراج تعبير خام في أجزاء مختلفة من استعلامك.
 
تستطيع أيضًا استخدام التوابع التالية بدلاً من استخدام <code>DB::raw</code> لإدراج تعبير خام في أجزاء مختلفة من استعلامك.
 
+
====selectRaw====
==== selectRaw ====
 
 
يمكن استخدام التابع <code>selectRaw</code> بدلاً من <code>select(DB::raw(...))‎</code>. يقبل هذا التابع مصفوفةً اختياريّةً من الارتباطات كمتغيّر وسيط ثاني لها:<syntaxhighlight lang="php">
 
يمكن استخدام التابع <code>selectRaw</code> بدلاً من <code>select(DB::raw(...))‎</code>. يقبل هذا التابع مصفوفةً اختياريّةً من الارتباطات كمتغيّر وسيط ثاني لها:<syntaxhighlight lang="php">
 
$orders = DB::table('orders')
 
$orders = DB::table('orders')
سطر 136: سطر 125:
  
 
</syntaxhighlight>
 
</syntaxhighlight>
 
+
====whereRaw / orWhereRaw====
==== whereRaw / orWhereRaw ====
 
 
<code>whereRaw</code> و <code>orWhereRaw</code> هما تابعان يمكن استخدامها لإضافة بند <code>where</code> خام لاستعلامك. تقبل هذه التوابع مصفوفة اختياريّة من الارتباطات كمتغيّر وسيط ثاني لها:<syntaxhighlight lang="php">
 
<code>whereRaw</code> و <code>orWhereRaw</code> هما تابعان يمكن استخدامها لإضافة بند <code>where</code> خام لاستعلامك. تقبل هذه التوابع مصفوفة اختياريّة من الارتباطات كمتغيّر وسيط ثاني لها:<syntaxhighlight lang="php">
 
$orders = DB::table('orders')
 
$orders = DB::table('orders')
سطر 143: سطر 131:
 
                 ->get();
 
                 ->get();
 
</syntaxhighlight>
 
</syntaxhighlight>
 
+
====havingRaw / orHavingRaw====
==== havingRaw / orHavingRaw ====
 
 
<code>havingRaw</code> و <code>orHavingRaw</code> هما تابعان يمكن استخدامها لتعيين سلسلة نصيّة خام كقيمة البند having. تقبل هذه التوابع مصفوفة اختيارية من الارتباطات كمتغيّر وسيط ثاني لها:<syntaxhighlight lang="php">
 
<code>havingRaw</code> و <code>orHavingRaw</code> هما تابعان يمكن استخدامها لتعيين سلسلة نصيّة خام كقيمة البند having. تقبل هذه التوابع مصفوفة اختيارية من الارتباطات كمتغيّر وسيط ثاني لها:<syntaxhighlight lang="php">
 
$orders = DB::table('orders')
 
$orders = DB::table('orders')
سطر 152: سطر 139:
 
                 ->get();
 
                 ->get();
 
</syntaxhighlight>
 
</syntaxhighlight>
 
+
====orderByRaw====
==== orderByRaw ====
 
 
يمكن استخدام التابع <code>orderByRaw</code> لتعيين سلسلة نصيّة خامة كقيمة البند order by:<syntaxhighlight lang="php">
 
يمكن استخدام التابع <code>orderByRaw</code> لتعيين سلسلة نصيّة خامة كقيمة البند order by:<syntaxhighlight lang="php">
 
$orders = DB::table('orders')
 
$orders = DB::table('orders')
سطر 159: سطر 145:
 
                 ->get();
 
                 ->get();
 
</syntaxhighlight>
 
</syntaxhighlight>
 
+
==معاملات ربط الجداول Joins==
== معاملات ربط الجداول Joins ==
+
====بند الربط الداخلي (Inner Join Clause)====
 
 
==== بند الربط الداخلي (Inner Join Clause) ====
 
 
يمكن استخدام منشئ الاستعلامات لكتابة تعابير الربط (join statements). لإجراء "ربط داخلي" بسيط، تستطيع استخدام التابع <code>join</code> على نسخة منشئ استعلامات. أوّل متغيّر وسيط يُمرّر إلى التابع <code>join</code> هو اسم الجدول الذي تحتاج للربط به في حين أن المُغيّرات الباقية تحدد قيود العمود للربط. تستطيع كما ترى الربط بعدّة جداول في استعلام واحد:<syntaxhighlight lang="php">
 
يمكن استخدام منشئ الاستعلامات لكتابة تعابير الربط (join statements). لإجراء "ربط داخلي" بسيط، تستطيع استخدام التابع <code>join</code> على نسخة منشئ استعلامات. أوّل متغيّر وسيط يُمرّر إلى التابع <code>join</code> هو اسم الجدول الذي تحتاج للربط به في حين أن المُغيّرات الباقية تحدد قيود العمود للربط. تستطيع كما ترى الربط بعدّة جداول في استعلام واحد:<syntaxhighlight lang="php">
 
$users = DB::table('users')
 
$users = DB::table('users')
سطر 170: سطر 154:
 
             ->get();
 
             ->get();
 
</syntaxhighlight>
 
</syntaxhighlight>
 
+
====بند الربط اليساري (Left Join Clause)====
==== بند الربط اليساري (Left Join Clause) ====
 
 
إن رغبت في عمل "ربط يساري" بدلاً من "ربط داخلي"، استخدم التابع <code>leftJoin</code>. يملك التابع <code>leftJoin</code> نفس توقيع التابع <code>join</code>:<syntaxhighlight lang="php">
 
إن رغبت في عمل "ربط يساري" بدلاً من "ربط داخلي"، استخدم التابع <code>leftJoin</code>. يملك التابع <code>leftJoin</code> نفس توقيع التابع <code>join</code>:<syntaxhighlight lang="php">
 
$users = DB::table('users')
 
$users = DB::table('users')
سطر 177: سطر 160:
 
             ->get();
 
             ->get();
 
</syntaxhighlight>
 
</syntaxhighlight>
 
+
====بند الربط المُتقاطع (Cross Join Clause)====
==== بند الربط المُتقاطع (Cross Join Clause) ====
 
 
لعمل "ربط مُتقاطع"، استخدم التابع <code>crossJoin</code> مع اسم الجدول الذي ترغب في الربط به. يولّد الربط المُتقاطع نتيجة ديكارتيّة بين الجدول الأول والجدول المربوط:<syntaxhighlight lang="php">
 
لعمل "ربط مُتقاطع"، استخدم التابع <code>crossJoin</code> مع اسم الجدول الذي ترغب في الربط به. يولّد الربط المُتقاطع نتيجة ديكارتيّة بين الجدول الأول والجدول المربوط:<syntaxhighlight lang="php">
 
$users = DB::table('sizes')
 
$users = DB::table('sizes')
سطر 184: سطر 166:
 
             ->get();
 
             ->get();
 
</syntaxhighlight>
 
</syntaxhighlight>
 
+
====بنود الربط المتقدّمة====
==== بنود الربط المتقدّمة ====
 
 
تستطيع أيضًا تحديد شروط ربط أكثر تقّدمًا. للبدء، مرّر Closure كالمتغيّر الوسيط الثاني في التابع <code>join</code>. سيتلقّى Closure كائن <code>JoinClause</code> والذي يسمح لك بتحديد القيود على البند join:<syntaxhighlight lang="php">
 
تستطيع أيضًا تحديد شروط ربط أكثر تقّدمًا. للبدء، مرّر Closure كالمتغيّر الوسيط الثاني في التابع <code>join</code>. سيتلقّى Closure كائن <code>JoinClause</code> والذي يسمح لك بتحديد القيود على البند join:<syntaxhighlight lang="php">
 
DB::table('users')
 
DB::table('users')
سطر 199: سطر 180:
 
         })
 
         })
 
         ->get();
 
         ->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>ملاحظة: يوجد أيضًا التابع unionAll وله نفس إمضاء التابع union.
 +
 +
== البنود Where ==
 +
 +
==== بنود Where البسيطة ====
 +
تستطيع استخدام التابع <code>where</code> على نسخة منشئ استعلامات لإضافة بنود where للاستعلام. يتطلب أبسط نداء where ثلاث وسائط. المتغيّر الوسيط الأول هو اسم العمود. المتغيّر الوسيط الثاني هو المُعامل (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>
 +
 +
==== العبارات Or ====
 +
تستطيع ربط قيود where معًا كما تستطيع إضافةً بنود <code>or</code> للاستعلام. يقبل التابع <code>orWhere</code> نفس المُتغيّرات الوسيطة كالتابع <code>where</code>:<syntaxhighlight lang="php">
 +
$users = DB::table('users')
 +
                    ->where('votes', '>', 100)
 +
                    ->orWhere('name', 'John')
 +
                    ->get();
 +
 +
 +
</syntaxhighlight>
 +
 +
=== بنود Where إضاقيّة ===
 +
 +
==== whereBetween ====
 +
يتحقّق التابع <code>whereBetween</code> من كون قيمة العمود بين قيمتين:<syntaxhighlight lang="php">
 +
$users = DB::table('users')
 +
                    ->whereBetween('votes', [1, 100])->get();
 +
</syntaxhighlight>
 +
 +
==== whereNotBetween ====
 +
يتحقّق التابع <code>whereBetween</code> من كون قيمة العمود خارج قيمتين:<syntaxhighlight lang="php">
 +
$users = DB::table('users')
 +
                    ->whereNotBetween('votes', [1, 100])
 +
                    ->get();
 +
</syntaxhighlight>
 +
 +
==== whereIn/whereNotIn ====
 +
يتحقق التابع <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>
 +
 +
==== whereNull / whereNotNull ====
 +
يتحقق التابع <code>whereNull</code> من كون قيمة العمود المحدّدة NULL:<syntaxhighlight lang="php">
 +
$users = DB::table('users')
 +
                    ->whereNull('updated_at')
 +
                    ->get();
 +
</syntaxhighlight>يتحقق التابع <code>whereNotNull</code> من عدم كون قيمة العمود المحدّدة NULL:<syntaxhighlight lang="php">
 +
$users = DB::table('users')
 +
                    ->whereNotNull('updated_at')
 +
                    ->get();
 +
</syntaxhighlight>
 +
 +
==== whereDate / whereMonth / whereDay / whereYear / whereTime ====
 +
يمكن استخدام التابع <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>
 +
 +
==== whereColumn ====
 +
يمكن استخدام التابع <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) ===
 +
قد تحتاج أحياناً لإنشاء بنود where متطوّرة أكثر حيث توجد عبارات مثل "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>ملاحظة: يجب دائمًا تجميع نداءات orWhere تجنّبًا لحدوث سلوك غير متوقع عند تطبيق النطاقات العامة.
 +
 +
=== البنود Where Exists ===
 +
يسمح لك التابع <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>
 +
 +
== الترتيب والتجميع والحد والإزاحة ==
 +
 +
==== orderBy ====
 +
يتيح لك التابع <code>orderBy</code> فرز نتائج الاستعلام حسب عمود محدّد. يجب أن يكون متغيّر التابع <code>orderBy</code> الوسيط الأول هو العمود الذي تريد الفرز حسبه بينما يتحكّم المتغيّر الوسيط الثاني في اتجاه الفرز وقد تكون إمّا <code>asc</code> أو <code>desc</code>:<syntaxhighlight lang="php">
 +
$users = DB::table('users')
 +
                ->orderBy('name', 'desc')
 +
                ->get();
 +
</syntaxhighlight>
 +
 +
==== latest / oldest ====
 +
يسمح لك التابعان <code>latest</code>  و <code>oldest</code> بترتيب النتائج حسب التاريخ بسهولة. تُرتّب النتيجة افتراضيًّا حسب العمود <code>created_at</code>. أو تستطيع تمرير اسم العمود الذي تريد الترتيب وفقًا له:<syntaxhighlight lang="php">
 +
$user = DB::table('users')
 +
                ->latest()
 +
                ->first();
 +
</syntaxhighlight>
 +
 +
==== inRandomOrder ====
 +
يُمكن استخدام التابع <code>inRandomOrder</code> لفرز نتائج الاستعلام عشوائيًّا. تستطيع مثلًا استخدام هذا التابع لجلب مستخدم عشوائي:<syntaxhighlight lang="php">
 +
$randomUser = DB::table('users')
 +
                ->inRandomOrder()
 +
                ->first();
 +
</syntaxhighlight>
 +
 +
==== groupBy / having ====
 +
يمكن استخدام التابعين <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>.
 +
 +
==== skip / take ====
 +
للحد من عدد من النتائج التي يردّها الاستعلام، أو لتخطّي عدد معيّن من النتائج في الاستعلام، تستطيع استخدام التابعين <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) ==
 +
قد ترغب أحيانًا في تطبيق بنود ما على الاستعلام فقط عندما تكون قيمة شيء آخر true. قد ترغب مثلًا بتطبيق عبارة <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>
  
==== ربط الاستعلام الفرعي ( Sub-Query Joins) ====
+
== مصادر ==
تستطيع استخدام التوابع  <code>joinSub</code> <code>leftJoinSub</code> و <code>rightJoinSub</code> و <code>rightJoinSub</code> لربط استعلام باستعلام فرعي. يتلقى كل تابع من هذه التوابع ثلاث مُتغيّرات وسيطة: الاستعلام الفرعي، واسم جدولها المستعار (table alias)، ونطاق مغلق يحدّد الأعمدة ذات الصلة:
+
* [https://laravel.com/docs/5.6/queries صفحة Database: Query Builder في توثيق Laravel الرسمي.]

مراجعة 22:15، 19 أكتوبر 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

يتحقّق التابع whereBetween من كون قيمة العمود بين قيمتين:

$users = DB::table('users')
                    ->whereBetween('votes', [1, 100])->get();

whereNotBetween

يتحقّق التابع whereBetween من كون قيمة العمود خارج قيمتين:

$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 فرز نتائج الاستعلام حسب عمود محدّد. يجب أن يكون متغيّر التابع orderBy الوسيط الأول هو العمود الذي تريد الفرز حسبه بينما يتحكّم المتغيّر الوسيط الثاني في اتجاه الفرز وقد تكون إمّا asc أو desc:

$users = DB::table('users')
                ->orderBy('name', 'desc')
                ->get();

latest / oldest

يسمح لك التابعان latest  و oldest بترتيب النتائج حسب التاريخ بسهولة. تُرتّب النتيجة افتراضيًّا حسب العمود created_at. أو تستطيع تمرير اسم العمود الذي تريد الترتيب وفقًا له:

$user = DB::table('users')
                ->latest()
                ->first();

inRandomOrder

يُمكن استخدام التابع inRandomOrder لفرز نتائج الاستعلام عشوائيًّا. تستطيع مثلًا استخدام هذا التابع لجلب مستخدم عشوائي:

$randomUser = DB::table('users')
                ->inRandomOrder()
                ->first();

groupBy / having

يمكن استخدام التابعين 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();

مصادر