اذهب إلى المحتوى

تجريد إعداد قواعد البيانات في لارافيل باستعمال عملية التهجير Migration والبذر Seeder


سامر سليمان

يتيح إطار العمل لارافيل Laravel المعتمد على لغة PHP عدة أدوات مُستخدمة مع قواعد البيانات ومن أهمها أداتي التهجير وتوليد البيانات أو البذر seeder اللتان تساعدان المطور على تهيئة قاعدة البيانات أو التخلص منها أو إعادة إنشائها بسرعة عالية، إذ تقلل هذه الأدوات من مشاكل عدم الاتساق الخاصة بقاعدة البيانات، والتي تظهر عند تشارك عدة مطورين باستخدام نفس قاعدة البيانات أو نفس التطبيق في الوقت ذاته. ينفذ المطوّر الذي يحتاج للعمل مع قواعد البيانات المشتركة مجموعةً بسيطةً من أوامر "artisan" لإعداد قاعدة البيانات لتصبح جاهزة للاستخدام.

نستخدم في عملنا هذا عدة عمليات تهجير لقواعد البيانات وتوليد بيانات نموذجية لملء قاعدة بيانات خاصة بتطبيق لارافيل توضيحي، وسنحذف الجداول ونعيد إنشائها عدة مرات باستخدام أوامر "artisan" فقط.

المتطلبات الأساسية

لاتباع خطوات هذا المقال ستحتاج ما يلي:

  • الوصول إلى حاسب يعمل بنظام التشغيل أوبنتو Ubuntu ذي رقم إصدار 18.04 أو إلى خادم تطوير يعمل بنفس نظام التشغيل المذكور بواسطة مستخدم ذي صلاحيات إدارة sudo ولا يفضل استخدام حساب الجذر Root لأسباب تتعلق بأمان الخادم كما يفضّل وجود جدار حماية نشط في حال العمل على خادم بعيد.
  • تثبيت الأداة دوكر Docker على الخادم.
  • تثبيت الأداة دوكر كومبوز Docker Compose على الخادم.

ملاحظة: نستخدم بيئة تطوير حاويات تديرها الأداة دوكر كومبوز لتشغيل التطبيق كما يمكن اختيار حزمة التخديم LEMP لتشغيله.

الخطوة 1- الحصول على التطبيق التوضيحي

نبدأ بتحميل تطبيق لارافيل التوضيحي من مخزن Github وننتقل إلى الفرع tutorial-02، الذي يحتوي إعداد الأداة دوكر كومبوز لتشغيل التطبيق على الحاويات، نحمّل التطبيق التوضيحي في المجلد الافتراضي ولكن يمكن اختيار أي مجلد آخر إذا دعت الحاجة لذلك، ومن ثم ننفذ الأوامر التالية:

cd ~
curl -L https://github.com/do-community/travellist-laravel-demo/archive/tutorial-2.0.1.zip -o travellist.zip

يبدأ تحميل الملف المضغوط بصيغة "zip." لذلك يجب عند انتهاء التحميل فك الضغط بعد التأكد من تحديث الحزم الخاصة بنظام التشغيل ما لم تكن محدّثة مؤخرًا، وذلك بتنفيذ الأوامر التالية:

sudo apt update

نثبت الحزمة "unzip" بتنفيذ الأمر:

sudo apt install unzip

مع إتمام عملية التثبيت نفك ضغط الملف بتنفيذ الأمر:

unzip travellist.zip

نعيد تسمية المجلد ليصبح باسم "travellist-demo" لسهولة الوصول إليه بتنفيذ الأمر:

mv travellist-laravel-demo-tutorial-2.0.1 travellist-demo

الخطوة 2- إعداد ملف "env." الخاص بالتطبيق

يتضمن الملف "env." عمليات الضبط الخاصة بالبيئة، مثل بيانات الاعتماد Credentials وأية معلومات تختلف بين عمليات نشر التطبيقات، لذلك لا يُضمّن هذا الملف ضمن ملفات التحكم بالإصدارات لكي لا تنتشر هذه المعلومات لجميع المستخدمين الذين يستخدمون صورة التطبيق لاحقًا.

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

توجد أولوية للقيم الموجودة في الملف "env." على القيم الموجودة في ملفات التهيئة الأخرى الموجودة في المجلد "config"، وتتطلب كل عملية تثبيت في بيئة جديدة ملف بيئة مخصص لتعريف معلومات خاصة، مثل إعدادات الاتصال بقاعدة البيانات، خيارات التصحيح debug والرابط الخاص بالتطبيق URL، إضافةً لبقية العناصر التي تختلف تبعاً للبيئة التي يعمل بها التطبيق.

ننتقل إلى المجلّد "travellist-demo" بتنفيذ الأمر:

cd travellist-demo

ننشئ ملف "env." جديد لتخصيص خيارات الإعداد لبيئة التطوير التي نعدها. ويمكننا نسخ الملف "example.env" الذي الموجود افتراضيًا ضمن أي تطبيق لارافيل بتنفيذ الأمر:

cp .env.example .env

نستخدم محرر نانو nano لتعديل محتوى الملف بتنفيذ الأمر:

nano .env

يبدو هذا الملف بالشكل التالي:

APP_NAME=Travellist
APP_ENV=dev
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost:8000 

LOG_CHANNEL=stack

DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=travellist
DB_USERNAME=travellist_user
DB_PASSWORD=password

يحتوي ملف "env." الحالي الخاص بتطبيق "travellist" التوضيحي إعدادات لاستخدام بيئة الحاويات التي أنشأناها باستخدام أداة دوكر كومبوز. لا نحتاج إلى تغيير أي من هذه القيم، ولكن يمكن تعديل DB_DATABASE و DB_USERNAME و DB_PASSWORD عند الحاجة، حيث أنّ هذه القيم تُسحب بالاعتماد على الملف docker-compose.yml تلقائيًا لإعداد قاعدة البيانات.

نتأكد من بقاء المتغير DB_HOST دون تغيير، لأنه يشير إلى اسم خادم قاعدة البيانات داخل بيئة دوكر كومبوز. نضغط على الاختصار "CTRL + X" ثم زر "Y" وأخيرًا زر الإدخال "Enter" عند الانتهاء من تعديل الملف.

ملاحظة: نحتاج عند تشغيل التطبيق على خادم LEMP إلى تغيير القيم المشار إليها لتتوافق مع إعدادات قاعدة البيانات بما في ذلك المتغير "DB_HOST".

الخطوة 3- تثبيت اعتماديات التطبيق مع كومبوزر

نستخدم الأداة كومبوزر لإدارة الاعتمادية الخاصة ببرامج PHP، إذ تُستخدم لتثبيت جميع اعتماديات التطبيق والتأكد من إمكانية استخدام أوامر "artisan".

نُظهر بيئة دوكر كومبوز حيث نبني صورة "travellist" لتشغيل التطبيق مثل خدمة "app" كما تُحمَّل جميع صور دوكر المتعلقة بالتطبيق مثل "nginx" و "db" لتشكيل بيئة التطبيق الكاملة. ننفذ الأمر التالي لتحقيق ذلك:

docker-compose up -d

وسيكون الخرج على النحو التالي:

Creating network "travellist-demo_travellist" with driver "bridge"
Building app
Step 1/11 : FROM php:7.4-fpm
 ---> fa37bd6db22a
Step 2/11 : ARG user
 ---> Running in 9259bb2ac034

Creating travellist-app   ... done
Creating travellist-nginx ... done
Creating travellist-db    ... done

تستغرق هذه العملية بضع دقائق حتى تكتمل ومن ثم نشغّل كومبوزر لتثبيت اعتماديات التطبيق. نستخدم الأمر docker-compose exec لتنفيذ أوامر كومبوزر وجميع الأوامر الأخرى ضمن حاوية خدمة التطبيق، إذ يسمح الأمرexec بتنفيذ أي أمر على الحاويات التي يديرها دوكر كومبوز، ويُكتب هذا الأمر وفقًا للصيغة التالية:

docker-compose exec service_name command

إذ يُستبدل المتغير service_name باسم الخدمة التي نرغب بتنفيذ الأمر عليها ويُستبدل المتغيرcommand بالأمر الذي نريد تطبيقه.

ملاحظة: نتجاهل عمليات الأمر docker-compose exec في حال استخدام خادم LEMP لتشغيل التطبيق التجريبي ونستخدم الأمر composer installعوضًا عنه.

ننفذ الأمر composer install ضمن الحاوية app بتطبيق الأمر:

docker-compose exec app composer install 

يظهر الخرج التالي بعد انتهاء التنفيذ:

Loading composer repositories with package information
Installing dependencies (including require-dev) from lock file
Package operations: 85 installs, 0 updates, 0 removals
  - Installing doctrine/inflector (1.3.1): Downloading (100%)         
  - Installing doctrine/lexer (1.2.0): Downloading (100%)         
  - Installing dragonmantank/cron-expression (v2.3.0): Downloading (100%)     

ننتظر إلى أن ينتهي كومبوزر من تثبيت اعتماديات التطبيق ومن ثم نستطيع تنفيذ أوامر "artisan". نختبر قدرة التطبيق على الاتصال بقاعدة البيانات بتنفيذ الأمر التالي الذي يفرّغ محتوى الجداول الموجودة مسبقًا:

docker-compose exec app php artisan db:wipe

يظهر الخرج التالي ما لم توجد مشكلة ما وعندها يكون التطبيق قادرًا على الاتصال بقاعدة البيانات:

Dropped all tables successfully.

نستخدم أداة "artisan" في تهجير وتوليد المعطيات بعد التأكد من قدرة التطبيق على الاتصال بقاعدة البيانات.

الخطوة 4- تهجير قاعدة البيانات

يتضمن الأمر "artisan" المُتاح افتراضيًا ضمن لارافيل عدة أوامر مساعدة تُستخدم في إدارة التطبيقات وتهيئة الأصناف الجديدة، نستخدم الأمر make:migration لتوليد صنف تهجير بيانات جديد بالشكل التالي:

docker-compose exec app php artisan make:migration create_places_table

تستنتج لارافيل من الأمر السابق أن العملية المطلوبة هي عملية إنشاء create وأنّ اسم الجدول المطلوب places. تحدد لارافيل إذا ما كانت عملية التهجير تنشئ جدولًا جديدًا أم لا بناءً على الاسم الوصفي الموجود في الأمر make:migration.

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

Created Migration: 2020_02_03_143622_create_places_table

يولَّد ملف جديد في المجلد "database/migrations" ضمن التطبيق ويُستخدم الطابع الزمني المضمّن في الملف المُنشأ تلقائيًا بوساطة لارافيل لتحديد الترتيب الذي تُنفّذ عمليات التهجير وفقًا له. نحرر الملف الذي ولّدناه باستخدام محرر النصوص المفضّل مع التركيز على استبدال اسم الملف أدناه باسم الملف الفعلي في حال وجود اختلاف بينهما.

nano database/migrations/2020_02_03_143622_create_places_table.php

يحتوي هذا الملف على صنفٍ يدعى CreatePlacesTable كما هو مبين فيما يلي:

<?php

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

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

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

يتضمن هذا الصنف تابعين هما up و down، اللتان تحتويان على شيفرة تهيئة التشغيل التي تحدد ما يحدث عند تنفيذ عملية التهجير وعند التراجع عنها.

نعدّل التابع up بحيث يعكس الجدول places البنية التي نستخدمها في تطبيقنا الحالي:

  • id: حقل المفتاح الأساسي.
  • name: حقل اسم المكان.
  • visited: حقل يشير إذا ما حدثت زيارة لهذا المكان مسبقًا أم لا.

يقدِّم مُنشِئ المخططات schema في لارافيل طرقًا لإنشاء وتعديل وحذف الجداول في قاعدة البيانات، إذ يعرّف الصنف Blueprint بنية الجدول ويقدم مجموعة توابع تحدّد حقول الجدول على نحوٍ مجرّد.

تُعد الشيفرة البرمجية المولّدة تلقائيًا حقلًا للمعرف الأساسي id كما ينشئ التابع timestamps حقلين من نوع معطيات timestamps يُعدَلان آليًا عند إضافة قيم إلى الجدول أو عند تعديل القيم الموجودة مسبقًا ضمن الجدول، ويُضاف إلى هذه الحقول حقلين إضافيين هما name و visited.

يُضبط نوع الحقل name ليكون سلسلة نصية "string" والحقل visited من النوع "boolean" وتوضع القيمة "0" في الحقل visited على أنها قيمة افتراضية لتمثّل عدم زيارة المكان مسبقًا ليصبح التابع الذي نعدّله على الشكل التالي:


    public function up()
    {
        Schema::create('places', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name', 100);
            $table->boolean('visited')->default(0);
            $table->timestamps();
        });
    }

ملاحظة: توجد قائمة بجميع أنواع الأعمدة المتاحة ضمن التوثيق الخاص بلارافيل.

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

artisan migrate

تُنشأ حاليًا جداول فارغة بالبنية التي اعتمدناها ولملء هذه الجداول ببيانات من اختيارنا لا بُد من استخدام مولّدات قواعد البيانات.

الخطوة 5- إنشاء مولدات قواعد البيانات

يستخدم الصنف الخاص Seeder لتوليد وإدخال البيانات إلى قاعدة البيانات، وتساعد هذه الميزة المطورين على إعادة إنشاء قاعدة البيانات وإدخال البيانات إليها بسرعة عالية دون الحاجة إلى عمليات يدوية لتحقيق ذلك. يولَّد صنف توليد بيانات آليًا باستخدام الأمر artisan ويحمل هذا الصنف الاسم PlacesTableSeeder بتنفيذ الأمر التالي:

docker-compose exec app php artisan make:seeder PlacesTableSeeder

يظهر ملف جديد اسمه "PlacesTableSeeder.php" ضمن المجلد "database/seeds". نحرّر محتوى الملف باستخدام محرر النصوص المفضّل:

nano database/seeds/PlacesTableSeeder.php

يتضمن الملف "PlacesTableSeeder.php" المُولّد تلقائيًا المحتوى التالي:

<?php

use Illuminate\Database\Seeder;

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

يحتوي الصنف على تابع فارغ run والذي يبدأ عمله عند تنفيذ الأمر db:seed. نعدّل محتوى هذا التابع ليتضمن التعليمات التي تُدخِل عينةً من البيانات إلى قاعدة البيانات، ونستخدم مُنشئ استعلامات لارافيل لتنفيذ ذلك.

يتيح منشئ استعلام لارافيل واجهة سلسة لعمليات قاعدة البيانات، مثل إدراج البيانات وتحديثها وحذفها واسترجاعها، كما أنّه يحمي قاعدة البيانات من هجمات حقن SQL. يمكن الوصول إلى باني الاستعلامات بالاعتماد على واجهة خاصة تدعى facade وهي وكيل Proxy ساكن إلى الأصناف الخاصة بقاعدة البيانات ضمن حاوية التطبيق.

ننشئ متغير ساكن من نوع مصفوفة ضمن الصنف والذي يحتوي على جميع الأماكن التي نرغب بإدخالها إلى قاعدة البيانات مثل مصفوفة. نستخدم حلقة foreach للتجوال على جميع القيم وإدخال كل منها بالاعتماد على باني الاستعلامات وسندعو هذا المتغير بالاسم places$كما في الشكل التالي:

<?php

use Illuminate\Database\Seeder;

class PlacesTableSeeder extends Seeder
{
    static $places = [
        'Berlin',
        'Budapest',
        'Cincinnati',
        'Denver',
        'Helsinki',
        'Lisbon',
        'Moscow',
        'Nairobi',
        'Oslo',
        'Rio',
        'Tokyo'
    ];

نستخدم عبارة use ضمن الصنف PlacesTableSeeder للمساعدة في الإشارة إلى واجهات قاعدة البيانات ضمن الشيفرة البرمجية كما يلي:

<?php

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;

class PlacesTableSeeder extends Seeder

نستخدم حلقة foreach للتجوال ضمن قيم المصفوفة places$ وإدخال كل من هذه القيم ضمن الجدول places باستخدام باني الاستعلامات كما يلي:

 
    public function run()
    {
        foreach (self::$places as $place) {
            DB::table('places')->insert([
                'name' => $place,
                'visited' => rand(0,1) == 1
            ]);
        }
    }

تتكرر تعليمات حلقة foreachعلى قيم المصفوفة الساكنة places$ واحدةً تلو الأخرى، ومع كل تكرار تُدخِل واجهة قاعدة البيانات سطرًا جديدًا ضمن الجدول places، بحيث يُضاف قيمة اسم المدينة الموجود في الجدول ضمن قاعدة البيانات من القيمة الموافقة في المصفوفة places$، كما توضع قيمة عشوائية إما أن تكون 0 أو 1 ضمن الحقل visited.

يصبح محتوى الشيفرة البرمجية الكاملة للصف PlacesTableSeeder بعد تجميع الأجزاء البرمجية السابقة على النحو التالي:

<?php

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;

class PlacesTableSeeder extends Seeder
{
    static $places = [
        'Berlin',
        'Budapest',
        'Cincinnati',
        'Denver',
        'Helsinki',
        'Lisbon',
        'Moscow',
        'Nairobi',
        'Oslo',
        'Rio',
        'Tokyo'
    ];

    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        foreach (self::$places as $place) {
            DB::table('places')->insert([
                'name' => $place,
                'visited' => rand(0,1) == 1
            ]);
        }
    }
}

لا تُحمّل أصناف توليد البيانات آليًا ضمن التطبيق، أي أنّه يجب تعديل الصنف DatabaseSeeder الرئيسي لتضمينها استدعاءً للصنف الذي أنشأناه. نحرر الملف "database/seeds/DatabaseSeeder.php" باستخدام محرر نانو أو أي محرر مفضل لديك بتنفيذ الأمر التالي:

nano database/seeds/DatabaseSeeder.php

لا يختلف الصنف "DatabaseSeeder" عن أية صنف آخر لتوليد البيانات، إذ أنّه يرث الصنف "Seeder" ويمتلك التابع "run" الذي نُحدّث محتواه ليتضمن استدعاءً للصنف "PlacesTableSeeder".

نحدّث محتوى التابع run ضمن الصنف DatabaseSeeder بإزالة التعليق الموجود ضمنه وإضافة ما يلي:


    public function run()
    {
        $this->call(PlacesTableSeeder::class);
    }

يصبح محتوى الشيفرة البرمجية للصنف DatabaseSeeder بعد التحديث كما يلي:

<?php

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        $this->call(PlacesTableSeeder::class);
    }
}

نحفظ الملف السابق وبهذا يكون قد انتهى إعداد كل من وظيفتي التهجير وتوليد البيانات الخاصتين بالجدول places ويبقى تنفيذ هذه الإجراءات.

الخطوة 6- ترحيل قواعد البيانات وتوليد البيانات

نتأكد من أنّ التطبيق الذي أعددناه جاهز للعمل، ومن ثم نُعدّ مفاتيح التشفير الخاصة بالتطبيق وعندها نستطيع اختبار التطبيق بطلبه ضمن المتصفح ومراقبة استجابة الخادم للطلب. نولّد مفاتيح التشفير الضرورية لعمل لارافيل وذلك باستخدام الأمر التالي:

docker-compose exec app php artisan key:generate

نطلب من المتصفح رابط التطبيق على المنفذ 8000 كما يلي:

http://server_host_or_ip:8000

نرى الاستجابة التالية على المتصفح:

browser_responce_befor_migration.jpg

نستنتج أن التطبيق يستطيع الاتصال بقاعدة البيانات لكنه لم يعثر على جدول باسم places ولذا ننشئ هذا الجدول بأمر التهجير التالي:

docker-compose exec app php artisan migrate

يظهر الخرج التالي:

Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table (0.06 seconds)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table (0.06 seconds)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated:  2019_08_19_000000_create_failed_jobs_table (0.03 seconds)
Migrating: 2020_02_10_144134_create_places_table
Migrated:  2020_02_10_144134_create_places_table (0.03 seconds)

نلاحظ تنفيذ عمليات تهجير إضافية إلى جانب التهجير create_places_table الذي أعددناه، إذ يجري إعداد هذه العمليات الإضافية عند تثبيت لارافيل. لا تفيد هذه الجداول ضمن نطاق العمل الحالي إلا أنها أساسيةٌ عند توسيع عمل التطبيق لتشمل المهام المجدولة والتعامل مع المستخدمين المسجّلين ولهذا لا نعدل في محتواها الآن.

تخلو الجداول السابقة من البيانات ومن أجل توليد بيانات في الجدول places نستخدم الأمر db:seed بالمحتوى الذي أنشأناه مسبقًا:

docker-compose exec app php artisan db:seed

يشغّل الأمر السابق المُولد الذي أنشأناه ضمن الصنف PlacesTableSeeder، ويظهر خرجٌ مشابهٌ لما يلي:

Seeding: PlacesTableSeeder
Seeded:  PlacesTableSeeder (0.06 seconds)
Database seeding completed successfully.

نعيد تحميل صفحة المتصفح لتظهر بالشكل التالي:

browser_responce_after_migration.jpg

يمكن إفراغ الجداول من بياناتها بتنفيذ الأمر:

docker-compose exec app php artisan db:wipe

ويكون الخرج على النحو التالي:

Dropped all tables successfully.

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

docker-compose exec app php artisan migrate --seed

ويكون الخرج على النحو التالي:

Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table (0.06 seconds)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table (0.07 seconds)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated:  2019_08_19_000000_create_failed_jobs_table (0.03 seconds)
Migrating: 2020_02_10_144134_create_places_table
Migrated:  2020_02_10_144134_create_places_table (0.03 seconds)
Seeding: PlacesTableSeeder
Seeded:  PlacesTableSeeder (0.06 seconds)
Database seeding completed successfully.

يمكن التراجع عن عملية التهجير بتنفيذ الأمر:

docker-compose exec app php artisan migrate:rollback

حيث يُستدعى التابع down من أجل كل عملية تهجير معرّفة ضمن الصنف وتكون هذه الأصناف مجمّعةً في مجلد "migrations" حيث تجري إزالة جميع الجداول التي أنشأتها أصناف التهجير باستثناء تلك التي أنشأها المستخدم يدويًا. يظهر لدينا خرج مشابهٌ لما يلي:

Rolling back: 2020_02_10_144134_create_places_table
Rolled back:  2020_02_10_144134_create_places_table (0.02 seconds)
Rolling back: 2019_08_19_000000_create_failed_jobs_table
Rolled back:  2019_08_19_000000_create_failed_jobs_table (0.02 seconds)
Rolling back: 2014_10_12_100000_create_password_resets_table
Rolled back:  2014_10_12_100000_create_password_resets_table (0.02 seconds)
Rolling back: 2014_10_12_000000_create_users_table
Rolled back:  2014_10_12_000000_create_users_table (0.02 seconds)

يفيد أمر التراجع بصورةٍ خاصة عندما نعدّل النماذج الخاصة بالتطبيق علمًا أنّ الأمر "db:wipe" لا يكون متاحًا للاستخدام كما في حالة اعتماد أكثر من نظام على قاعدة بيانات مشتركة.

الخاتمة

تضمنّت هذه المقالة توضيحًا بمدى أهمية عمليات تهجير وتوليد البيانات ضمن قاعدة البيانات من أجل إعداد واختبار قواعد البيانات الخاصة بتطبيقات لارافيل من الإصدار 6.

ترجمة –وبتصرف- للمقال How To Use Database Migrations and Seeders to Abstract Database Setup in Laravel لصاحبه Erika Heidi.

اقرأ أيضًا


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

أفضل التعليقات

لا توجد أية تعليقات بعد



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...