مقدمة إلى التعامل مع قواعد البيانات في Laravel

من موسوعة حسوب
اذهب إلى: تصفح، ابحث

مقدمة

يُبسّط Laravel التعامل مع قواعد البيانات بشكل كبير عبر مجموعة متنوعة من الأسندة الخلفية (backends) قواعد البيانات إمّا باستخدام  لغة الاستعلام البنيوية SQL خام أو باستخدام منشئ الاستعلامات الفصيح (fluent query builder)، أو باستخدام رابط الكائنات بالعلاقات Eloquent. يدعم Laravel حاليًا أربع قواعد بيانات:

الضبط

تقع إعدادات قاعدة بيانات تطبيقك في 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.

مصادر