تهجير قواعد البيانات في Laravel 5


محمد أحمد العيل

يوفر تهجير قواعد البيانات Database migration في Laravel آليات لإنشاء الجداول Tablesوالتعديل عليها بغض النظر نظام إدارة قواعد البيانات المستخدم. يعني هذا أنك لن تضطر للاهتمام بالاختلافات بين نظم إدارة قواعد البيانات في صياغة أوامر SQL. يمكّن التهجير أيضا من التراجع والعودة إلى ما كانت عليه قاعدة البيانات قبل آخر التعديلات.

هذا الدرس جزء من سلسلة تعلم Laravel والتي تنتهج مبدأ "أفضل وسيلة للتعلم هي الممارسة"، حيث ستكون ممارستنا عبارة عن إنشاء تطبيق ويب للتسوق مع ميزة سلة المشتريات. يتكون فهرس السلسلة من التالي:

laravel5-database-migration.thumb.png.1f

يمكن النظر إلى تهجير قواعد البيانات كما لو كان نظام إدارة نسخ خاص بقواعد البيانات، إذ يتيح لفريق العمل سهولة تغيير مخطّط Schema البيانات وتشاركه.

نكمل في هذا الدرس اعتمادا على ما أنشأناه في الدروس السابقة من السلسلة. يغطي الدرس المواضيع التالية:

  • متطلبات التهجير.
  • أمر Artisan لتهجير قواعد البيانات.
  • بنية التهجير.
  • إنشاء جدول بآلية التهجير.
  • استخدام آلية التهجير للتراجع Rollback عن التعديلات.
  • بذر قواعد البيانات Database seeding.
  • بنية قاعدة البيانات الخاصة بمشروع Larashop.
  • ملفات التهجير لقاعدة بيانات Larashop.

متطلبات التهجير

يجب أولا إنشاء قاعدة بيانات في نظام إدارة قواعد البيانات المستخدم (MySQL في حالتنا) وإعداد معطيات الاتصال بها في Laravel ولدى أداة سطر الأوامر Artisan.

إنشاء قاعدة بيانات

نفذ الأمر التالي في سطر أوامر MySQL أو استخدم التطبيق المفضّل لديك (PHPMyAdmin مثلا) لإنشاء قاعدة بيانات larashop:

CREATE DATABASE `larashop`;

إعداد Laravel للاتصال بقاعدة البيانات

أعددنا Laravel في الدرس الأول من هذه السلسلة للاتصال بقاعدة بيانات باسم larashop. في ما يلي تذكير بخطوات الإعداد.

افتح الملف config/database.php واعثر على الأسطُر التالية:

'mysql' => [
  'driver' => 'mysql',
  'host' => env('DB_HOST', 'localhost'),
  'database' => env('DB_DATABASE', 'forge'),
  'username' => env('DB_USERNAME', 'forge'),
  'password' => env('DB_PASSWORD', ''),
  'charset' => 'utf8',
  'collation' => 'utf8_unicode_ci',
  'prefix' => '',
  'strict' => false,
],

حدّث القيم التالية لتوافق إعدادات MySQL لديك:

'database'  => env('DB_DATABASE', 'larashop'),
'username'  => env('DB_USERNAME', 'root'),
'password'  => env('DB_PASSWORD', 'melody'),

إعداد معطيات اتصال Artisan بقاعدة البيانات

يواجه الكثير من المطورين رسالة الخطأ التالية عند العمل على تهجير قواعد البيانات باستخدام أداة Artisan:

Access denied for user 'homestead'@' localhost' (using password: YES)

ستظهر الرسالة أعلاه حتى ولو كانت معطيات الاتصال في الملف configuration/database.php صحيحة. يعود السبب في ذلك إلى أن Artisan يستخدم المعطيات الموجودة في الملف env.. الحل هو إذن تحرير الملف env. الواقع في مجلد التطبيق، ستجد ما يلي:

APP_ENV=local
APP_DEBUG=true
APP_KEY=aqk5XHULL8TZ8t6pXE43o7MBSFchfgy2

DB_HOST=localhost
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret

CACHE_DRIVER=file
SESSION_DRIVER=file
QUEUE_DRIVER=sync

MAIL_DRIVER=smtp
MAIL_HOST=mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null

حدث المتغيرات التالية:

DB_HOST=localhost
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret

لتصبح:

DB_HOST=localhost
DB_DATABASE=larashop
DB_USERNAME=root
DB_PASSWORD=melody

احرص على موافقة اسم قاعدة البيانات، اسم المستخدم وكلمة مروره للمعطيات لديك. احفظ التعديلات.

تهجير قواعد البيانات بأداة Artisan

ينشئ أمر artisan ملفا على المسار database/migrations لكل عملية تهجير. يمكن تغيير المسار الخاص بحفظ ملفات التهجير إن أردت ولكننا هنا سنكتفي بالمسار المبدئي.

ننفذ الأمر التالي لإنشاء أول ملف تهجير:

php artisan make:migration create_drinks_table

تظهر رسالة باسم ملف التهجير الجديد. اخترنا اسم create_drinks_table للدلالة على أن التهجير ينشئ جدولا باسم drinks في قاعدة البيانات. نتيجة الأمر هي إنشاء ملف للتهجير بنفس الاسم الذي أعطيناه مع إضافة ختم زمني قبله، مثلا:

2015_12_21_215845_create_drinks_table.php

بنية ملف التهجير

ندرس الآن محتوى ملف التهجير الذي أنشأناه للتو. افتح الملف التالي لرؤية محتواه (انتبه إلى أن اسم الملف يبدأ بختم زمني للحظة إنشائه):

database/migrations/2015_12_21_215845_create_drinks_table.php

نجد ما يلي:

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateDrinksTable extends Migration
{
    /**
    * Run the migrations.
    *
    * @return void
    */
    public function up()
    {
        //
    }

    /**
    * Reverse the migrations.
    *
    * @return void
    */
    public function down()
    {
        //
    }
}
  • يعرف ملف التهجير صنفا جديدا باسم CreateDrinksTable يمدد الصنف Migration:

CreateDrinksTable extends Migration
  • داخل الصنف CreateDrinksTable توجد دالة باسم up. تنفّذ تعليمات الدالة up عند تشغيل التهجير.

  • توجد أيضا دالة باسم down في الصنف CreateDrinksTable. تنفذ تعليمات الدالة down عند التراجع عن تغييراتِ تهجير.

ملف تهجير لإنشاء جدول بقاعدة البيانات

ليمكن إنشاء جدول في قاعدة البيانات فجيب تعريف حقوله في ملف التهجير. نعيد فتح ملف التهجير السابق ونعدله ليصبح محتواه التالي :

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateDrinksTable extends Migration {

    /**
    * Run the migrations.
    *
    * @return void
    */
    public function up() {
        Schema::create('drinks', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name',75)->unique();
            $table->text('comments')->nullable();
            $table->integer('rating');
            $table->date('juice_date');
            $table->timestamps();        
        });
    }

    /**
    * Reverse the migrations.
    *
    * @return void
    */
    public function down() {
        Schema::dropIfExists('drinks');
    }
}
  • في الدالة up: نستدعي الدالة create المعرَّفة في الصنف Schema ونمرر لها معطيين، الأول اسم الجدول الذي نريد إنشاءه drinks، والمعطى الثاني دالة غير محدّدة الاسم تعرّف حقول الجدول. نستخدم كائنا من صنف Blueprint لتعريف الجدول.
  • نعرف أول حقل من الجدول وهو الحقل id. تعرف الدالة increments التابعة للصنف Blueprint عددا طبيعيا (عدد صحيح إشارته موجبة) يزداد تلقائيّا مع كل إدخال للبيانات في الجدول.
  • الحقل الثاني هو حقل الاسم name، الذي نعرفه بالدالة string. تنشئ الدالة stringحقلا من سلسلة محارف مع تحديد طول السلسلة (75 في المثال). نعلّم الحقل name بالدالة unique \لجعله وحيدا وهو ما يعني أنه لا يمكن لتسجيلتين في الجدول أن تحويا نفس القيمة بالنسبة لهذا الحقل.
  • الحقل الثالث comments نصي، وتستخدم الدالة text لتعريفه. نتيح إمكانية ألا يحوي الحقل بيانات باستخدام الدالة nullable.
  • الحقل الرابع rating للتقيمات. نستخدم الدالة integer للإشارة إلى أنه عدد صحيح.
  • ثم نضيف حقلا لتخزين تاريخ المشروب juice_date ونستخدم الدالة date لهذا الغرض.
  • تُستخدم الدالة timestamps لإضافة حقلين هما created_at وupdated_at في الجدول تلقائيا. الحقلان عبارة عن ختم زمني ل، على التوالي، تاريخ إضافة التسجيلة إلى قاعدة البيانات وتاريخ آخر تحديث عليها.
  • في الدالة down نحذف الجدول drinks من قاعدة البيانات في حالة وجوده.

ننفذ بعد حفظ ملف التهجير الأمر التالي:

php artisan migrate

ستظهر مخرجات في سطر الأوامر على النحو التالي:

Migration table created successfully.
Migrated: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_100000_create_password_resets_table
Migrated: 2015_12_21_215845_create_drinks_table

إن نظرت في جداول قاعدة البيانات الآن فستجد التالي:

01_artisan__migrate.thumb.png.6f23c5237b

ستلاحظ وجود أربعة جداول من بينها جدول drinks. الجداول الأخرى أنشأها Laravel لأن ملفات تهجيرها تأتي مبدئيا مع Laravel.

التراجع عن التعديلات

يوفر التهجير إمكانية التراجع عن تعديلاته والعودة إلى حالة قاعدة البيانات قبل تنفيذه. أنشأنا في الفقرة السابقة جداول في قاعدة البيانات، ننفذ الأمر التالي للتراجع عن ذلك:

php artisan migrate:rollback

تظهر الرسائل التالية:

Rolled back: 2015_12_21_215845_create_drinks_table
Rolled back: 2014_10_12_100000_create_password_resets_table
Rolled back: 2014_10_12_000000_create_users_table

إن أعدت التحقق في MySQL سترى أن الجدول drinks لم يعد موجودا.

نعيد إنشاء الجدول بتنفيذ التهجير مرة أخرى:

php artisan migrate

تمكن ملاحظة أن تنفيذ التهجير يكون بالتسلسل الزمني التصاعدي لتاريخ إنشاء ملفات التهجير (من الأقدم إلى الأحدث)، في ما يكون التراجع بتنفيذ ملفات التهجير حسب التسلسل الزمني التنازلي (من الأحدث إلى الأقدم).

إدارة جداول البيانات في Laravel باستخدام التهجير

سنرى في هذه الفقرة كيفية استخدام التهجير للقيام بأشغال شائعة على جداول قواعد البيانات.

إدراج بيانات

سنرى الآن كيفية استخدام التهجير لإدراج بيانات في جدول أثناء إنشائه. ننشئ جدولا بالموظفين employees وندرج فيه 33 تسجيلة بالاعتماد على مكتبة Faker (سنخصص درسا لتفصيل استخدام Faker).

نفذ الأمر التالي لإنشاء ملف تهجير لجدول employees:

php artisan make:migration employees

نفتح الملف المنشأ للتو ونضيف الشفرة التالية:

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class Employees extends Migration
{
    /**
    * Run the migrations.
    *
    * @return void
    */
    public function up()
    {
        Schema::create('employees', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->string('email')->unique();
            $table->string('contact_number');
            $table->timestamps();       
        }); 

        $faker = Faker\Factory::create();
        $limit = 33;

        for ($i = 0; $i < $limit; $i++) {
            DB::table('employees')->insert([ //,
               'name' => $faker->name,
               'email' => $faker->unique()->email,
               'contact_number' => $faker->phoneNumber,
            ]);
        }
    }

    /**
    * Reverse the migrations.
    *
    * @return void
    */
    public function down()
    {
        Schema::dropIfExists('employees');
    }
}
  • ننشئ كائنا من صنف Faker بالتعليمة

$faker = Faker\Factory::create();
  • نحدد عدد التسجيلات التي نود إدراجها: limit$.

  • نستخدم حلقة for التكرارية لإضافة التسجيلات إلى الجدول. تولد التعليمة faker->name$ اسما وهميّا، faker->unique()->email$ اسم بريد وحيد وfaker->phoneNumber$ رقم هاتف وهميا.

الأمر التالي ينفذ التهجير:

php artisan migrate

تظهر الرسالة التالية دلالة على تهجير الجدول employees:

Migrated: 2015_12_21_225233_employees

 

إن بحثت الآن عن محتوى الجدول employees، مثلا بتنفيذ الاستعلام التالي في سطر أوامر MySQL:

SELECT * FROM employees;

ستحصُل على أسماء الموظفين، عناوينهم البريدية وأرقام هواتفهم.

نتراجع عن إنشاء الجدول employees بتنفيذ الأمر:

php artisan migrate:rollback

تظهر رسالة دلالة على التراجع عن إنشاء الجدول. نفتح ملف التهجير للتعديل عليه ثم نضع الشفرة الخاصة بإدراج بيانات وهمية بين علامتي تعليق، هكذا:

/*
$faker = Faker\Factory::create();

$limit = 33;

for ($i = 0; $i < $limit; $i++) {
  DB::table('employees')->insert([ //,
    'name' => $faker->name,
    'email' => $faker->unique()->email,
    'contact_number' => $faker->phoneNumber,
  ]);
}
*/

احفظ ملف التهجير ثم نفذ الأمر:

php artisan migrate

سيُنشأ جدول employees من جديد ولكن هذه المرة دون إدراج تسجيلات في الجدول.

إضافة عمود إلى جدول أو حذفه منه

نفرض أننا نود إضافة عمود جديد gender لتخزين جنس الموظّف، مباشرة بعد العمود contact_number. ننفذ الأمر التالي لإنشاء ملف تهجير باسم add_gender_to_employees مع تحديد الجدول الذي نريد العمل عليه وهو employees:

php artisan make:migration add_gender_to_employees --table=employees

تشير التعليمة table=employees-- إلى أننا نريد العمل على الجدول employees الموجود في قاعدة البيانات.

افتح ملف التهجير المنشأ بعد الأمر السابق، وعدله ليصبح على النحو التالي:

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class AddGenderToEmployees extends Migration
{
    /**
    * Run the migrations.
    *
    * @return void
    */
    public function up()
    {
        Schema::table('employees', function (Blueprint $table) {
            $table->string('gender')->after('contact_number');
        });
    }

    /**
    * Reverse the migrations.
    *
    * @return void
    */
    public function down()
    {
        Schema::table('employees', function (Blueprint $table) {
            $table->dropColumn('gender');
        });
    }
}
  • في الدالة up أضفنا حقلا جديدا من نوع string (سلسلة محارف) وحددنا مكانه بأنه بعد العمود contact_number.
  • في الدالة down نحذف الحقل gender.

الآن عند تنفيذ أمر التهجير php artisan migrate ستلاحظ إضافة عمود جديد باسم gender بعد عمود contact_number.

تغيير نوع عمود

يحتاج تغيير نوع العمود لتثبيت حزمة Doctrine Database Abstract Layer, DBAL. تُستخدم هذه الحزمة لتهجيرات التعديل على الجداول Alter table.

سنستخدم أداة إدارة الاعتماديات Composer لتثبيت الحزمة. افتح ملف composer.json الذي يوجد في مجلد التطبيق. ابحث عن مقطع require:

"require": {
  "php": ">=5.5.9",
  "laravel/framework": "5.2.*"
},

توجد في هذا المقطع حزم المكتبات التي يحتاجها تطبيقنا. حتى الآن توجد حزمتان فقط هما php وlaravel. يشير الجزء الأول (قبل النقطتين) إلى اسم الحزمة، في ما يشير الثاني لإصدارها. نضيف حزمة dbal` إلى هذه الاعتماديات، وذلك على النجو التالي:

"require": {
  "php": ">=5.5.9",
  "laravel/framework": "5.2.*",
  "doctrine/dbal": "v2.4.2"
},

لاحظ  الفاصلة اللاتينية التي أضفناها بعد حزمة Laravel.

نفذ الأمر التالي لتحديث المشروع:

composer update

عند إنشاء العمود gender لم نحدد طول الحقل، أي أنه سيأخذ الطول المبدئي للحقول من نوع string وهو255 محرفا. ننشئ ملف تهجير جديدا لتعديل طول الحقل ليصبح 5 كحد أقصى.

نعدل الملف على النحو التالي:

php artisan make:migration modify_gender_in_employees --table=employees

قبول فراغ الحقول في الجدول

يفترض Laravel عند إنشاء الحقول أنها لا تقبل فراغ القيمة، أي أنه يجب ذكر قيمة للحقل عند إدراج تسجيلات في الجدول. يمكننا تغيير هذا الإعداد المبدئي وجعل قيمة حقل ما اختيارية. سنأخذ الحقل gender للتمثيل به.

ننشئ ملفا للتهجير:

php artisan make:migration make_gender_null_in_employees --table=employees

ثم نعدله على النحو التالي:

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class MakeGenderNullInEmployees extends Migration
{
    /**
    * Run the migrations.
    *
    * @return void
    */
    public function up()
    {
        Schema::table('employees', function (Blueprint $table) {
            $table->string('gender', 5)->nullable()->change();
        });
    }

    /**
    * Reverse the migrations.
    *
    * @return void
    */
    public function down()
   {
        Schema::table('employees', function (Blueprint $table) {
            $table->string('gender', 5)->change();
        });
    }
}
  • تجعل الدالة nullable الحقل gender يقبل قيما فارغة.
php artisan migrate

إضافة مفتاح خارجي Foreign key

نصنف موظفينا حسب القسم الذي يعملون فيه. ننشئ جدولا للأقسام depts ثم نضيف مفتاحا خاريجا في جدول الموظفين employees.

الأمر أدناه ينشئ ملف تهجير لجدول الأقسام:

php artisan make:migration depts

عدل ملف التهجير:

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class Depts extends Migration
{
    /**
    * Run the migrations.
    *
    * @return void
    */
    public function up()
    {
        Schema::create('depts', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->timestamps();
        });
    }

    /**
    * Reverse the migrations.
    *
    * @return void
    */
    public function down()
    {
        Schema::dropIfExists('depts');
    }
}

ثم ننفذ أمر التهجير لإنشاء الجدول:

php artisan migrate

يُشترط لتصح علاقة عبر مفتاح خارجي بين جدولين أن يكون المفتاح الخارجي والمفتاح الرئيس Primary key متطابقين في النوع. استخدمنا في تعريف المفتاح الرئيس idضمن الجدول depts دالة increments التي تعطي النوع عددا طبيعيا من عشرة أرقام ;(unsigned integer INT(10 وهو ما يعني أننا سنعطي نفس النوع للمفتاح الخارجي الذي سننشئه في الجدول employees. الفرق أن المفتاح الخارجي لا يزداد تلقائيا لذا سنستخدم الدالة unsignedInteger التي لها نفس مفعول increments من حيث نوع الحقل وطوله، مع فرق أنها لا تضيف الازدياد التلقائي.

ملحوظة: حتى تمكن إضافة مفتاح خارجي في الجدول employees يجب أن يكون الجدول فارغا (بدون تسجيلات). لهذا السبب علقنا في فقرة ماضية الشفرة الخاصة بـFaker.

نفذ الأمر التالي لإنشاء ملف تهجير لإضافة حقل المفتاح الخارجي dept_id إلى الجدول employees:

php artisan make:migration add_dept_id_in_employees --table=employees

ثم نعدل ملف التهجير:

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class AddDeptIdInEmployees extends Migration
{
    /**
    * Run the migrations.
    *
    * @return void
    */
    public function up()
    {
        Schema::table('employees', function (Blueprint $table) {
            $table-> unsignedInteger ('dept_id')->after('gender');
            $table->foreign('dept_id')
                  ->references('id')->on('depts')
                  ->onDelete('cascade');
        });
    }

    /**
    * Reverse the migrations.
    *
    * @return void
    */
    public function down()
    {
        Schema::table('employees', function (Blueprint $table) {
            $table->dropColumn('dept_id');
        });
    }
}

ثم ننفذ التهجير:

php artisan migrate 

بذر قواعد البيانات

يشير مصطلح البذر Seeding إلى عملية إضافة بيانات وهمية لأغراض الاختبار في قواعد البيانات. نطبق هذا الإجراء على جدول drinks الذي أنشأناه في أول الدرس.

نفذ الأمر التالي لإنشاء ملف للبذر:

php artisan make:seeder DrinksTableSeeder

ينشئ الأمر ملفا باسم DrinksTableSeeder.php على المسار database/seeds. افتح الملف:

<?php

use Illuminate\Database\Seeder;

class DrinksTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        //
    }
}

يمدد الصنف DrinksTableSeeder الصنف Seeder ويعرّف الدالة run التي تُنفّذ عند تشغيل أمر البذر في Artisan. 

عدل الملف ليصبح محتواه التالي:

<?php

use Illuminate\Database\Seeder;

class DrinksTableSeeder extends Seeder {

    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run() {
        
    DB::table('drinks')->insert([ 
           'name' => 'Orange Juice',
           'comments' => 'Rich in C vitamin',
           'rating' => 9,
           'juice_date' => '2015-12-20',
       ]);


}

أضفنا في الدالة run أمر إدراج في جدول البيانات drinks ومررنا مصفوفة توافق عناصرها حقول الجدول مع تحديد قيم عناصر المصفوفة. ننفذ الأمر أمر البذر لإضافة التسجيلة أعلاه إلى الجدول:

php artisan db:seed --class=DrinksTableSeeder

نمرر لأمر البذر php artisan db::seed اسم الملف المراد تنفيذه.

الآن عند التحقق نجد في جدول قاعدة البيانات التسجيلة التالية:

02_seeding.thumb.png.52cc250e5d895deb9d8

قاعدة البيانات الخاصة بمشروع Larashop

تعرفنا في الفقرات الماضية على أساسيات التهجير في Laravel. سنجعل هذه المعرفة موضع التطبيق لإنشاء قاعدة بيانات لمشروع Larashop.

ستشنرك جميع الجداول في الحقول التالية التي أنشأناها لأغراض الفحص والتدقيق.

التسلسلالحقلنوع البياناتالوصف
1created_at    Timestamp    ختم زمني لتاريخ إدراج التسجيلة
2updated_at    Timestamp    ختم زمني لتاريخ تحديث التسجيلة
3created_at_ip   (Varchar(45    عنوان IP المستخدم لإدراج التسجيلة
4updated_at_ip    (Varchar(45    عنوان IP المستخدم لتحديث التسجيلة

جدول منشورات المدونة

التسلسلالحقلنوع البياناتالوصف
1id    INT    مفتاح رئيس (AUTOINCREMENT) عدد طبيعي يزداد تلقائيا
2url    (Varchar(255    رابط الصفحة
3title    (Varchar(140     عنوان الصفحة
4description    (Varchar(170     وصف يظهر في محركات البحث
5content    Text     محتوى الصفحة أو المنشور 
6conblogtent    (Tinyint(1    يحدد ما إذا كان المنشور صفحة

جدول التصنيفات

التسلسلالحقلنوع البياناتالوصف
1id    INT    مفتاح رئيس (AUTOINCREMENT) عدد طبيعي يزداد تلقائيا
2name    (Varchar(255    اسم التصنيف

جدول العلامات التجارية

التسلسلالحقلنوع البياناتالوصف
1id    INT    مفتاح رئيس (AUTOINCREMENT) عدد طبيعي يزداد تلقائيا
2name    (Varchar(255    اسم العلامة التجارية

جدول المنتجات

لكل منتج تصنيف وعلامة تجارية وحيدين.

التسلسلالحقلنوع البياناتالوصف
1id    INT     مفتاح رئيس (AUTOINCREMENT) عدد طبيعي يزداد تلقائيا
2name    (Varchar(255    اسم المنتج
3title    (Varchar(140    عنوان المنتج
4description    (Varchar(500    عنوان المنتج
5price    int    ثمن المنتج
6category_id    int    معرف تصنيف المنتج
7brand_id    int    معرف العلامة التجارية للمنتج

ملفات التهجير لجداول قاعدة بيانات المشروع

سننشئ في هذه الفقرة ملفات تهجير لجداول البيانات المذكورة أعلاه؛ سنضيف أيضا بعض البيانات الوهمية إلى الجداول باستخدام آلية البذر التي تعرفنا عليها سابقا.

توليد ملفات التهجير

افتح سطر الأوامر ونفذ الأوامر التالية لتوليد ملفات الجداول:

جدول منشورات المدونة:

php artisan make:migration create_posts_table

جدول تصنيفات المنتجات

php artisan make:migration create_categories_table

جدول العلامات التجارية للمنتجات

php artisan make:migration create_brands_table

جدول المنتجات

php artisan make:migration create_products_table

تحرير ملفات التهجير

ننتقل لتحرير كل ملف من ملفات التهجير.

جدول منشورات المدونة

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreatePostsTable extends Migration {

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up() {
        Schema::create('posts', function (Blueprint $table) {
            $table->increments('id');
            $table->string('url', 255)->unique();
            $table->string('title', 140);
            $table->string('description', 170);
            $table->text('content');
            $table->boolean('blog');
            $table->timestamps();
            $table->string('created_at_ip');
            $table->string('updated_at_ip');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down() {
        Schema::drop('posts');
    }
}

جدول التصنيفات

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateCategoriesTable extends Migration {

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up() {
        Schema::create('categories', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name', 255)->unique();
            $table->timestamps();
            $table->string('created_at_ip');
            $table->string('updated_at_ip');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down() {
        Schema::drop('categories');
    }
}

جدول العلامات التجارية

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateBrandsTable extends Migration {

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up() {
        Schema::create('brands', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name', 255)->unique();
            $table->timestamps();
            $table->string('created_at_ip');
            $table->string('updated_at_ip');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down() {
        Schema::drop('brands');
    }
}

جدول المنتجات

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateProductsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('products', function (Blueprint $table) {
                $table->increments('id');
                $table->string('name', 255)->unique();
                $table->string('title', 140);
                $table->string('description', 500);
                $table->integer('price');
                $table->unsignedInteger('category_id');
                $table->unsignedInteger('brand_id');
                $table->timestamps();
                $table->string('created_at_ip');
                $table->string('updated_at_ip');
                // مفتاح خارجي على جدول التصنيفات
                $table->foreign('category_id')
                ->references('id')->on('categories')
                ->onDelete('cascade');
                // مفتاح خارجي على جدول العلامات التجارية
                $table->foreign('brand_id')
                ->references('id')->on('brands')
                ->onDelete('cascade');
            });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('products');
    }
}

بذر قاعدة بيانات المشروع

ندرج بيانات وهمية في جداول قاعدة البيانات قصدَ الاختبار.

أنشئ ملفات البذر بتنفيذ الأوامر أدناه على التوالي:

php artisan make:seeder CategoriesTableSeeder
php artisan make:seeder BrandsTableSeeder
php artisan make:seeder ProductsTableSeeder

يحوي جدول المنتجات مفتاحين خارجيين لجدولي التصنيف والعلامة التجارية. لذا يجب البدء بهما (لا يصح إدراج مفتاح خارجي لتسجيلة غير موجودة في الجدول الذي مثل المفتاح الخارجي مرجعا إليه).

  • بذر جدول التصنيفات

<?php

use Illuminate\Database\Seeder;

class CategoriesTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        DB::table('categories')->insert(['name' => 'MENS']);
        DB::table('categories')->insert(['name' => 'WOMENS']);
        DB::table('categories')->insert(['name' => 'KIDS']);
        DB::table('categories')->insert(['name' => 'FASHION']);
        DB::table('categories')->insert(['name' => 'CLOTHING']);
    }
}
  • بذر جدول العلامات التجارية
<?php

use Illuminate\Database\Seeder;

class BrandsTableSeeder extends Seeder {

    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run() {
        DB::table('brands')->insert(['name' => 'ACNE']);
        DB::table('brands')->insert(['name' => 'RONHILL']);
        DB::table('brands')->insert(['name' => 'ALBIRO']);
        DB::table('brands')->insert(['name' => 'ODDMOLLY']);
    }
}
  • بذر جدول المنتجات
<?php

use Illuminate\Database\Seeder;

class ProductsTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        DB::table('products')->insert(['name' => 'Mini skirt black edition', 'title' => 'Mini skirt black edition','description' => 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna','price' => 35,'category_id' => 1,'brand_id' => 1,]);
        DB::table('products')->insert(['name' => 'T-shirt blue edition', 'title' => 'T-shirt blue edition','description' => 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna','price' => 64,'category_id' => 2,'brand_id' => 3,]);
        DB::table('products')->insert(['name' => 'Sleeveless Colorblock Scuba', 'title' => 'Sleeveless Colorblock Scuba','description' => 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna','price' => 13,'category_id' => 3,'brand_id' => 2,]);
    }
}

ثم ننفذ أوامر البذر لكل جدول.

خاتمة

تعرفنا في هذا الدرس على تهجير قواعد البيانات وبذرها في Laravel. كما أننا حددنا هيكلة قاعدة بيانات المشروع الذي نعمل عليه. في الدروس القادمة سنتعرف على إطار عمل Eloquent الذي سنعتمد عليه للتخاطب مع قاعدة البيانات وعرض محتوياتها عند الاقتضاء.

ترجمة -وبتصرّف- لمقال Laravel 5 Migrations لصاحبه Rodrick Kazembe.



4 اشخاص أعجبوا بهذا


تفاعل الأعضاء


جزاك الله خيرا . في انتظار التتمة

شارك هذا التعليق


رابط هذا التعليق
شارك على الشبكات الإجتماعية


يجب أن تكون عضوًا لدينا لتتمكّن من التعليق

انشاء حساب جديد

يستغرق التسجيل بضع ثوان فقط


سجّل حسابًا جديدًا

تسجيل الدخول

تملك حسابا مسجّلا بالفعل؟


سجّل دخولك الآن