قواعد البيانات: منشئ الاستعلامات
مقدمة
يوفّر منشئ استعلامات قاعدة بيانات 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();