قواعد البيانات: البدايات
مقدّمة
يُبسّط Laravel التعامل مع قواعد البيانات بشكل كبير عبر مجموعة متنوعة من الأسندة الخلفية (backends) قواعد البيانات إمّا باستخدام لغة الاستعلام البنيوية SQL خام أو باستخدام منشئ الاستعلامات الفصيح (fluent query builder)، أو باستخدام رابط الكائنات بالعلاقات Eloquent. يدعم Laravel حاليًا أربع قواعد بيانات:
- MySQL
- PostgreSQL
- SQLite
- SQL Server
الضبط
تقع إعدادات قاعدة بيانات تطبيقك في config/database.php
. تستطيع في هذا الملف تعريف جميع اتصالات قاعدة بياناتك لإضافةً لتحديد الاتصال الافتراضي. تتوافر أمثلة عن معظم أنظمة قواعد البيانات المدعومة في هذا الملف.
عيّنة إعدادات بيئة Laravel الافتراضيّة جاهزة مسبقًا للاستخدام مع Laravel Homestead، وهو جهاز افتراضي (virtual machine) ملائم لتطوير Laravel على جهازك المحلّي. أنت حر طبعًا في تعديل هذا الضبط حسب حاجة قاعدة بياناتك المحليّة.
ضبط SQLite
تستطيع ضبط متغيرات بيئتك بسهولة بعد إنشاء قاعدة بيانات SQLite جديدة باستخدام أمر مثلtouch
database/database.sqlite
، للإشارة إلى قاعدة البيانات الجديدة باستخدام مسارها المطلق (absolute path):
DB_CONNECTION=sqlite
DB_DATABASE=/absolute/path/to/database.sqlite
اتصالات القراءة والكتابة (Read & Write Connections)
قد ترغب في بعض الأحيان في استخدام اتصال قاعدة بيانات واحد لتعابير SELECT
، وآخر لتعابير INSERT
و UPDATE
و DELETE
. يسهّل Laravel هذا الأمر بشكل كبير كما ستُستخدم الاتصالات المناسبة سواء استخدمت استعلامات خامّة أو منشئ الاستعلامات (query builder) أو رابط الكائنات بالعلاقات Eloquent.
فلنلق نظرة على هذا المثال لمعرفة كيفيّة ضبط اتصالات القراءة والكتابة:
'mysql' => [
'read' => [
'host' => ['192.168.1.1'],
],
'write' => [
'host' => ['196.168.1.2'],
],
'sticky' => true,
'driver' => 'mysql',
'database' => 'database',
'username' => 'root',
'password' => '',
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
],
لاحظ إضافة ثلاثة مفاتيح لمصفوفة الضبط: read
و write
و sticky
. تحتوي مفاتيح read
write
على قيم مصفوفة تحتوي بدورها على مفتاح واحد: host. ستّدمج بقيّة خيارات قاعدة البيانات للاتصالات read
و write
من المصفوفة mysql الرئيسية.
لا تحتاج إلّا لوضع العناصر في المصفوفتين read
و write
إن أردت إعادة تعريف القيَم من المصفوفة الأساسية. إذا في هذه الحالة ستُستخدم 192.168.1.1 كالمُضيف للإتصال "read" بينما تُستخدم 192.168.1.2 للإتصال "write". ستُشارك كل بيانات اعتماد قاعدة البيانات (database credentials)، واللاحقات (prefix)، ومجموعة الأحرف، وجميع الخيارات الأخرى في المصفوفة mysql الرئيسية عبر كلا الاتصالين.
الخيار sticky
الخيار sticky
هو قيمة اختيارية يمكن استخدامها للسماح بالقراءة الفورية للسجلات التي كُتيت بقاعدة البيانات أثناء دورة الطلب الحالية. ستستخدم أي عمليات "read" أخرى الاتصال "write" إن مُكّن الخيار sticky
ونُفّذت العملية "write" على قاعدة البيانات أثناء دورة الطلب الحالية. ممّا يضمن إمكانيّة قراءة أي بيانات مكتوبة خلال دورة الطلب فورًا من قاعدة البيانات خلال نفس الطلب. تقرير صلاحيّة هذا السلوك لتطبيقك متروك لك.
استخدام عدّة اتصالات بقاعدة بيانات
تستطيع عند استخدام عدّة اتصالات الوصول إلى كل اتصال عبر التابع connection
على الواجهة DB
. يجب أن يطابق name
المُمرّر للتابع connection
أحد الاتصالات المذكورة في ملف الضبط config/database.php
:
$users = DB::connection('foo')->select(...);
تستطيع أيضًا الوصول إلى نسخة PDO الأساسي باستخدام التابع getPdo
على نسخة الاتصال:
$pdo = DB::connection()->getPdo();
تنفيذ استعلامات SQL الخامة
تستطيع تنفيذ الاستعلامات باستخدام الواجهة الساكنة DB
بمجرد إعداد اتصال قاعدة بياناتك. توفر الواجهة الساكنة DB
توابع لكل نوع استعلام: select ،update ،insert ،delete ،statement.
تنفيذ استعلام Select
تستطيع استخدام التابع select
على الواجهة DB
الساكنة لتنفيذ استعلام بسيط:
<?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::select('select * from users where active = ?', [1]);
return view('user.index', ['users' => $users]);
}
}
أول متغيّر وسيط مُرّر للتابع select
هو استعلام SQL الخام، في حين أن ثاني متغيّر وسيط هو أي إرتباطات معامل (parameter bindings) يجب ربطها بالاستعلام.
عمومًا هذه هي قيم قيود عبارة where
. يوفر ارتباط المعاملة حماية ضد حقن SQL (أي SQL injection).
يرد التابع select
دائمًا مصفوفة array
من النتائج. ستصبح كل نتيجة داخل المصفوفة كائن PHP StdClass
، مما يسمح لك بالوصول إلى قيم النتائج:
foreach ($users as $user) {
echo $user->name;
}
استخدام الارتباطات المُسمّاة (Using Named Bindings)
تستطيع تنفيذ استعلام باستخدام الروابط المسماة بدلًا من استخدام ? لتمثيل ارتباطات المعاملات:
$results = DB::select('select * from users where id = :id', ['id' => 1]);
تنفيذ تعبير Insert
تستطيع استخدام التابع insert
على واجهة DB
الساكنة لتنفيذ تعبير insert
. يأخذ هذا التابع الاستعلام SQL الخام كمتغيّره الوسيط الأول وإرتباطه كمتغيّر وسيط ثاني مثل مثال select
:
$results = DB::select('select * from users where id = :id', ['id' => 1]);
تنفيذ تعبير Update
يجب أن يُستخدم التابع update
لتحديث السجلات الموجودة في قاعدة البيانات. سيرد حينها عدد الصفوف المتأثرة بالتعبير:
$affected = DB::update('update users set votes = 100 where name = ?', ['John']);
تنفيذ تعبير Delete
يجب أن يُستخدم التابع delete
لحذف السجلات من قاعدة البيانات. مثل update
سيُرد عدد الصفوف المتأثرة:
$deleted = DB::delete('delete from users');
تنفيذ تعبير عام (Running A General Statement)
لا ترد بعض عبارات قاعدة البيانات أي قيمة. تستطيع استخدام التابع statement
على واجهة DB
الساكنة بالنسبة لهذه العمليات:
DB::statement('drop table users');
الاستماع لأحداث الاستعلام
إذا رغبت في تلقي كل استعلام SQL ينفّذه تطبيقك، تستطيع استخدام التابع listen
. هذا التابع مفيد بتسجيل الاستعلامات أو تصحيح الأخطاء. تستطيع تسجيل مستمع استعلامك في موفّر خدمات:
<?php
namespace App\Providers;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* تمهيد أي خدمات التطبيق.
*
* @return void
*/
public function boot()
{
DB::listen(function ($query) {
// $query->sql
// $query->bindings
// $query->time
});
}
/**
* سجّل موفّر الخدمات.
*
* @return void
*/
public function register()
{
//
}
}
عمليّات قواعد البيانات (Database Transactions)
تستطيع استخدام التابع transaction
على واجهة DB
الساكنة لتنفيذ مجموعة من العمليات داخل عمليّة قاعدة البيانات. إن طُرح استثناء داخل نطاق العمليّة المُغلق Closure سيرجع أمر تراجع (rolled back) المعاملة تلقائيًا. إذا نُفّذت Closure بنجاح، ستحفظ التغييرات المُجراة على قاعدة البيانات تلقائيًا. لا داعي للقلق بشأن التراجع (rolling back) أو الحفظ (committing) يدويًا أثناء استخدام التابع transaction
:
DB::transaction(function () {
DB::table('users')->update(['votes' => 1]);
DB::table('posts')->delete();
});
مُعالجة الاستعصاء (Handling Deadlocks)
يقبل التابع transaction
متغيّرًا وسيطًا ثانيًا اختياريًّا يحدّد عدد مرّات إعادة محاولة المعاملة عند حدوث استعصاء. سيُطرح استثناء بمجرد استنفاد هذه المحاولات:
DB::transaction(function () {
DB::table('users')->update(['votes' => 1]);
DB::table('posts')->delete();
}, 5);
استخدام المعاملات يدويًّا
تستطيع استخدام التابع beginTransaction
على الواجهة الساكنة DB
إن أردت بدء المعاملة يدويًا والتحكّم الكامل في rollbacks
و commits
:
DB::beginTransaction();
تستطيع التراجع عن المعاملة عبر التابع rollBack
:
DB::rollBack();
وأخيرًا، تستطيع حفظ المعاملة عبر التابع commit
:
DB::commit();
ملاحظة: تتحكم توابع معاملة الواجهة الساكنة DB
في المعاملات لكل من منشئ الاستعلامات ورابط الكائنات بالعلاقات Eloquent.