نگار جوادزاده
نگار جوادزاده
خواندن ۳ دقیقه·۵ سال پیش

مبحث Migration ها در Laravel

migrations in laravel
migrations in laravel

چرا Migration ؟

تصور کنید می خواهید یک پروژه لاراول را با دوستانتان توسعه دهید، برای این کار علاوه بر استفاده اشتراکی از کد های پروژه، میبایست طرحواره پایگاه داده ی پروژه را نیز با یکدیگر به اشتراک بگذارید! حال فرض کنید یکی از هم تیمی های شما قصد در ایجاد یک ستون در یک جدول در پایگاه داده دارد، برای اینکه در ادامه روند پروژه شما مشکلی پیش نیاید و تمام اعضای گروه آخرین نسخه به روز طرحواره پایگاه داده را داشته باشند، تمام اعضای گروه باید آن ستون را با همان نام و در همان جدول به صورت دستی ایجاد کنند. این همه کار فقط برای ایجاد یک ستون!!!

این مشکل را لاراول با استفاده از migration ها حل کرده است. در ادامه بیشتر با migration ها آشنا می شویم:

ساخت یک Migration :

اگر با لاراول آشنا باشید قطعا با دستورات php artisan آشنایی دارید!

برای ساخت یک migration از دستور

  • php artisan make : migration

استفاده میکنیم. migration ایجاد شده در مسیر database/migrations قرار دارد.

php artisan help make:migration
php artisan help make:migration

با توجه به راهنمایی تصویر بالا میتوان از این دستور استفاده کرد. برای مثال برای ساخت یک جدول به نام users ،از دستور

  • php artisan make:migration create_users_table - -create=users

استفاده میکنیم. در دستور بالا به چند نکته باید توجه کرد:

1)قبل از قسمت options ما timestamp را create_users_table نام گذاری کردیم. این نام گذاری اختیاریست ولی بهتر است نام مناسب (قراردادی) در نظر بگیرید.

2)اگر از قبل جدول users را دارید و فقط میخواهید اطلاعاتی را به آن migrateکنید بهتر است به جای create - - از table - - استفاده کنید.

3)همان طور که گفته شد این فایل به طور پیش فرض در مسیر database/migrations ایجاد خواهد شد ولی اگر بخواهید مسیر آن را تغییر دهید میتوانید از path - - استفاده کنید. توجه داشته باشد که مسیر تعیین شده بایستی نسبت به مسیر پایه اپلیکیشن تعیین شود.

ساختار Migration

یک کلاس migration دارای 2 متد up و down می باشد. که متد up برای افزودن جدول ها یا ستون ها و یا index های جدید در پایگاه داده استفاده می شود. و متد down معکوس متد up بوده و عملیات انجام گرفته توسط این متد را به عقب برمیگرداند. در هر 2 متد میتوان از سازنده طرحواره(schema builder) استفاده کرد.

برای مثال در قطعه کد زیر نحوه ایجاد جدول users را با تعدادی ستون مشاهده میکنید. (البته توجه داشته باشید که این قطعه کد را داخل فایل migration ایجاد شده با دستور

  • php artisan make:migration create_users_table - -create=users

قرار میدهیم.)

<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateUsersTable extends Migration{ /** * Run the migrations. * * @return void */ public function up(){ Schema::create('users', function (Blueprint $table) { $table->id(); $table->string('name'); $table->string('last_name')->nullable(); $table->string('email')->unique(); $table->string('password'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down(){ Schema::dropIfExists('users'); } }


توجه کنید که به تعداد جدول های ایجاد شده (Schema::create) در متد up بایستی در متد down آن را به عقب برگردانید (Schema::dropIfExists).

اجرای تمام Migration ها

برای اجرای migration های موجود در database/migrations میبایست دستور

  • php artisan migrate

را در خط فرمان اجرا کنیم. که ترتیب اجرای این migration ها بر اساس timestamp های آن ها خواهد بود(تاریخ و ساعتی که موقع ایجاد، لاراول برای آن ها در نظر میگیرد).

اجرای migration تحت هر شرایطی در مرحله ی production:
برخی از عملیات migration مخرب است ، به این معنی که ممکن است باعث از بین رفتن اطلاعات شما شود. برای اینکه از اجرای این دستورات در برابر پایگاه داده در محیط production محافظت کنید ، قبل از اجرای دستورات از شما خواسته می شود تا تأیید کنید. برای مجبور کردن دستورات بدون درخواست تایید، از force - - استفاده کنید. php artisan migrate - - force

بازگرداندن Migration ها به عقب

برای برگرداندن آخرین عملیات migration ، می توانید از دستور برگشت استفاده کنید. این دستور آخرین دسته migration ها را برمیگرداند ، که ممکن است شامل چند فایل migartion باشد:

  • php artisan migrate:rollback

برای بازگرداندن تمام migration های اپلیکشن خود، میتوانید از دستور تنظیم مجدد استفاده کنید.

  • php artisan migrate:reset

برای بازگرداندن و اجرای مجدد تمام migration در یک دستور از دستور refresh استفاده میکنیم.

  • php artisan migrate:refresh

برای حذف و اجرای مجدد تمام migration ها در یک دستور میتوان از دستور fresh استفاده کرد.

  • php artisan migrate:fresh

برای بازگرداندن تعداد محدودی از migration ها میتوانید از step - - استفاده کنید. برای مثال برای بازگرداندن 2 ،migration آخر از دستور

  • php artisan migrate:rollback - -step=2

استفاده میکنیم. این گزینه برای تمام دستورات برگشت صادق است.

توجه کنید که با اجرای این دستورها اطلاعات ثبت شده در جدول های بازگردانده شده حذف میشود. بنابراین برای ساخت دوباره اطلاعات داخل جدول از seed- - استفاده کنید.

جدول ها

ساخت جدول جدید با schema

برای ایجاد جدول جدید در پایگاه داده، از روش ایجاد در نمای Schema استفاده کنید.() create دو آرگومان را می پذیرد: اولین آرگمان، نام جدول است ، و دومی یک Closure است که یک شیء Blueprint را دریافت می کند که برای تعریف جدول جدید استفاده می شود. هنگام ایجاد جدول ، می توانید از هر یک از روش های ستون سازنده schema برای تعریف ستون های جدول استفاده کنید.

Schema::create('users', function(Blueprint $table){ $table->id(); });

بررسی وجود جدول / ستون

با استفاده از متد های hasTable و hasColumn می توانید وجود جدول یا ستون را بررسی کنید.

if (Schema::hasTable('users')){ // your code }
if (Schema::hasColumn('users', 'email')){ // your code }

اتصال به پایگاه داده و گزینه های جدول:

اگر می خواهید یک عملیات schema را بر روی اتصال بانک اطلاعاتی انجام دهید که اتصال پیش فرض شما نیست ، از متد اتصال استفاده کنید:

Schema::connection('foo')->create('users', function(Blueprint $table){ $table->id(); });

شما می توانید از دستورات زیر برای سازندهschemaبرای تعریف گزینه های جدول استفاده کنید:

  • موتور ذخیره سازی جدول (MySQL) را مشخص کنید.
$table->engine = 'InnoDB';
  • یک مجموعه کاراکتر پیش فرض تنظیم شده برای جدول (MySQL) مشخص کنید.
$table->charset = 'utf8mb4';
  • یک ترکیب بندی پیش فرض برای جدول (MySQL) مشخص کنید.
$table->collation = 'utf8mb4_unicode_ci';
  • یک جدول موقتی ایجاد کنید (به جز SQL Server).
$table->temporary();

تغییر نام جدول

برای تغییر نام جدول موجود ، از روش تغییر نام استفاده کنید:

Schema::rename($from, $to);

حذف جدول

برای حذف یک جدول موجود ، می توانید از روش های drop یا dropIfExists استفاده کنید:

Schema::drop('users');
Schema::dropIfExists('users');
تغییر نام جداول با کلیدهای خارجی
قبل از تغییر اسم جدول، بایستی بررسی شود که تمامیconstraint های کلید خارجی موجود در جدول دارای اسم مشخص و صریح در فایل هایmigration هستند. در غیر این صورت لاراول خود یک اسم بر اساس قرارداد تخصیص می دهد و این امر سبب می شود constraint کلید خارجی به اسم قدیمی جدول اشاره کند.



ستون ها

ساخت ستون ها

میتوانید از متد table در نمای Schema برای به روزرسانی جداول موجود استفاده کنید. مانند متد create ، متد table دو آرگومان را می پذیرد: نام جدول و Closureکه نمونه Blueprint را دریافت می کند که می توانید برای اضافه کردن ستون به جدول استفاده کنید.

Schema::table('users', function (Blueprint $table) { $table->string('email'); });

انواع ستون موجود

سازندهschema، انواع مختلفی از ستون ها را در اختیار شما قرار می دهد که می توانید هنگام ساخت جداول خود استفاده کنید. من در این جا به برخی از آن ها اشاره میکنم.

  • معادل('table->bigIncrements('id$
$table->id();
  • معادل ('table->unsignedBigInteger('user_id$
$table->foreignId('user_id');
  • مقدار ستون id (کلید اصلی) را با یک معادل "عدد صحیح بزرگ بدون علامت" افزایش می دهد.
$table->bigIncrements('id');
  • ستون معادل BIGINT در پایگاه داده
$table->bigInteger('votes');
  • ستون معادل BLOB در پایگاه داده
$table->binary('data');
  • ستون معادل BOOLEAN در پایگاه داده
$table->boolean('confirmed');
  • ستون معادل CHAR در پایگاه داده با (حداکثر) طول مشخص.
$table->char('name', 100);
  • ستون معادل DATE در پایگاه داده
$table->date('created_at');
  • ستون معادل DECIMAL در پایگاه داده با دقت (کل رقم) و مقیاس (رقم اعشار).
$table->decimal('amount', 8, 2);
  • ستون معادل DOUBLE در پایگاه داده با دقت (کل رقم) و مقیاس (رقم اعشار).
$table->double('amount', 8, 2);
  • ستون معادل ENUM در پایگاه داده
$table->enum('level', ['easy', 'hard']);
  • ستون معادل FLOAT در پایگاه داده با دقت (کل رقم) و مقیاس (رقم اعشار).
$table->float('amount', 8, 2);
  • ستون معادل افزایش خودکار در پایگاه داده (کلید اصلی).
$table->increments('id');
  • ستون معادل INTEGER در پایگاه داده
$table->integer('votes');
  • ستون معادل IP address در پایگاه داده
$table->ipAddress('visitor');
  • ستون معادل JSON در پایگاه داده
$table->json('options');
  • ستون معادل JSONB در پایگاه داده
$table->jsonb('options');
  • ستون معادل LONGTEXT در پایگاه داده
$table->longText('description');
  • ستون remember_token را با نوع داده ای (VARCHAR (100 و امکان NULL بودن به پایگاه داده اضافه می کند.
$table->rememberToken();
  • ستون معادل VARCHAR در پایگاه داده با (حداکثر) طول مشخص
$table->string('name', 100);
  • ستون معادل TEXT در پایگاه داده
$table->text('description');
  • ستون های created_at و updated_at را به جدول پایگاه داده اضافه می کند.
$table->timestamps(0);
لیست کامل این ستون ها را میتوانید از Laravel.com مطالعه فرمایید.

اصلاح کنندگان ستون

علاوه بر انواع ستون های ذکر شده در بالا ، چندین تغییر دهنده ستون وجود دارد که می توانید هنگام افزودن ستون به جدول پایگاه داده از آنها استفاده کنید. برای مثال ، برای ساختن ستون "nullable" ، می توانید از متد nullable استفاده کنید.

Schema::table('users', function(Blueprint $table){ $table->string('email')->nullable(); });

در زیر لیستی از برخی column modifier های موجود را مشاهده می کنید. در این لیست index modifier ها لحاظ نشده است.

  • ستون های INTEGER را به صورت خودکار افزایش میدهد. (کلید اصلی)
->autoIncrement()
  • مجموعه کاراکتر را برای ستون مشخص میکند (MySQL).
->charset('utf8mb4')
  • مقدار "پیش فرض" برای ستون را مشخص میکند.
->default($value)
  • به طور پیش فرض مقدار NULL را به ستون می دهد.
->nullable($value = true)
  • ستون های INTEGER را به صورت بدون علامت تنظیم کنید (MySQL)
->unsigned()
لیست کامل این ستون ها را میتوانید از Laravel.com مطالعه فرمایید.

ویرایش ستون های جدول

پیش از اقدام به ویرایش یک ستون، بایستی doctrine/dbal را به فایل composer.json اضافه کنید. با بهره گیری از کتابخانه ی Doctrine DBAL می توان وضعیت جاری ستون را مشخص کرده و query های مورد نیاز SQL را جهت اعمال تغییرات تعریف شده به ستون مورد نظر بکار برد.

composer require doctrine/dbal

متد change به شما امکان می دهد نوع و ویژگی های ستون های موجود را تغییر دهید. به عنوان مثال ، شما ممکن است بخواهید اندازه یک ستون string را افزایش دهید. برای مثال، اندازه ستون name را با این دستور از 25 به 50 افزایش میدهیم:

Schema::table('users', function(Blueprint $table){ $table->string('name', 50)->change(); });

یا حتی میتوان به آن ستون ویژگی nullable را افزود.

Schema::table('users', function (Blueprint $table) { $table->string('name', 50)->nullable()->change(); });
توجه داشته باشید که فقط ستون های زیر قابل تغییر هستند.
bigInteger, binary, boolean, date, dateTime, dateTimeTz, decimal, integer, json, longText, mediumText, smallInteger, string, text, time, unsignedBigInteger, unsignedInteger, unsignedSmallInteger , uuid.

برای تغییر نام ستون ، می توانید از متد renameColumn در سازنده schema استفاده کنید.

Schema::table('users', function (Blueprint $table){ $table->renameColumn('from', 'to'); });
هر جدولی که ستون از نوع enum در خود داشته باشد، اجازه ی تغییر هیچ یک از ستون ها را به شما نمی دهد (این امکان در حال حاضر پشتیبانی نمی شود).

حذف ستون های جدول

برای حذف ستون ، از متد dropColumn در سازنده schema استفاده کنید. قبل از حذف ستون ها از پایگاه داده SQLite ، شما نیاز دارید که doctrine/dbal را به فایل composer.json اضافه کنید.و دستور به روزرسانی composer را در ترمینال خود اجرا کنید تا کتابخانه نصب شود.

Schema::table('users', function (Blueprint $table){ $table->dropColumn('votes'); });

شما می توانید با دادن آرایه ای از نام ستون ها به متد dropColumn به عنوان آرگمان، چندین ستون را از یک جدول حذف کنید.

Schema::table('users', function (Blueprint $table){ $table->dropColumn(['votes', 'avatar', 'location']); });



فهرست ها(indexes)

ساخت فهرست

سازنده طرحواره Laravel از چندین نوع فهرست مختلف پشتیبانی می کند. مثال زیر یک ستون email جدید ایجاد می کند و مشخص می کند که مقادیر آن باید منحصر به فرد باشند. برای ایجاد index ، می توانیم متد unique را بر روی تعریف ستون قرار دهیم:

$table->string('email')->unique();

ممکن است بعد از تعریف ستون ، بخواهید index ایجاد کنید. مثلا:

$table->string('email'); $table->unique('email');

شما حتی می توانید مجموعه ای از ستون ها را به یک متد indexمنتقل کنید تا یک compound (یا composite) ایجاد شود:

$table->index(['account_id', 'created_at']);

لاراول به طور خودکار یک نام index بر اساس جدول ، نام ستون ها و نوع فهرست تولید می کند، اما شما میتوانید یک آرگومان دوم را برای مشخص کردن نام indexخود به متد ارسال کنید:

$table->unique('email', 'unique_email');

انواع فهرست موجود

هر متد index برای مشخص کردن نام index ، یک آرگومان دوم اختیاری را می پذیرد. در صورت خالی گذاشتن آرگمان دوم ، نام از نام جدول و ستون (های) مورد استفاده برای index و همچنین نوع index گرفته می شود.

  • یک کلید اصلی را اضافه می کند.
$table->primary('id');
  • کلیدهای composite را اضافه می کند.
$table->primary(['id', 'parent_id']);
  • اندیس منحصر به فرد اضافه می کند.
$table->unique('email');
  • اندیس ساده اضافه می کند.
$table->index('state');
  • اندیس مخصوص اضافه می کند. (ب جز SQLite)
$table->spatialIndex('location');

لاراول از مجموعه کاراکتر utf8mb4 به صورت پیش فرض استفاده می کند ، که شامل پشتیبانی از ذخیره "emojis" در پایگاه داده نیز می باشد. اگر نسخه ای از MySQL قدیمی تر از نسخه 5.7.7 یا MariaDB قدیمی تر از نسخه 10.2.2 را اجرا می کنید ، ممکن است لازم باشد که طول رشته پیش فرض تولید شده توسط migration ها را به صورت دستی پیکربندی کنید تا MySQLبتواند برای آنها index ایجاد کند. شما می توانید با فراخوانی متد Schema::defaultStringLength از AppServiceProvider خود پیکربندی کنید.

use Illuminate\Support\Facades\Schema; /** * Bootstrap any application services. * * @return void */ public function boot(){ Schema::defaultStringLength(191); }
یا می توانید گزینه innodb_large_prefix را برای پایگاه داده خود فعال کنید. برای راهنمایی در مورد نحوه فعال سازی صحیح این گزینه به مستندات پایگاه داده خود مراجعه کنید.

تغییر نام فهرست(index)

برای تغییر نام یک فهرست ، می توانید از متد renameIndex استفاده کنید. این روش نام index فعلی را به عنوان اولین آرگومان و نام جدید مورد نظر به عنوان آرگومان دوم خود می پذیرد.

$table->renameIndex('from', 'to');

حذف فهرست(index)

برای حذف یک index ، باید نام index را مشخص کنید. به طور پیش فرض ، Laravel به طور خودکار یک نام index را بر اساس نام جدول ، نام ستون فهرست شده و نوع فهرست اختصاص می دهد(اسم جدول، اسم ستون فهرست شده و نوع آن فهرست را به صورت زنجیره ای به هم متصل می کند). در اینجا چند مثال آورده شده است.

  • یک کلید اصلی را از جدول "users" حذف می کند.
$table->dropPrimary('users_id_primary');
  • یک فهرست منحصر به فرد را از جدول "users" حذف می کند.
$table->dropUnique('users_email_unique');
  • فهرست اصلی را از جدول "geo" حذف می کند.
$table->dropIndex('geo_state_index');
  • یک فهرست مخصوص را از جدول "geo" (به جز SQLite) حذف می کند.
$table->dropSpatialIndex('geo_location_spatialindex');

اگر مجموعه ای از ستون ها را به متد ای منتقل کنید که index ها را حذف می کند ، در آن صورت برای اندیس ها بر اساس اسم جدول، ستون و نوع کلید اسم قراردادی ایجاد می شود.

Schema::table('geo', function(Blueprint $table){ $table->dropIndex(['state']); // Drops index 'geo_state_index' });

محدودیت های کلید خارجی(Foreign Key)

لاراول همچنین امکان افزودن محدودیت کلید خارجی در جدول را فراهم می آورد. کلید خارجی برای تعریف و حفظ ارتباط بین جداول در پایگاه داده بکار می رود. برای مثال یک ستون user id در جدول posts ایجاد می کنیم که به ستون id در جدول users اشاره می کند.

Schema::table('posts', function(Blueprint $table){ $table->unsignedBigInteger('user_id'); $table->foreign('user_id')->references('id')->on('users'); });

از آنجا که این syntax ترجیحا" درازاست ، Laravel روشهای مختصرتری را ارائه می دهد که با استفاده از قرارداد یک تجربه بهتر برای توسعه دهنده رقم میزند. مثال بالا می تواند به صورت زیر نوشته شود:

Schema::table('posts', function (Blueprint $table){ $table->foreignId('user_id')->constrained(); });

در این جا به جای ('references('id')->on('users از foreignId و ()constrained استفاده میکند. که foreignId معادل unsignedBigInteger است. اگر نام ستون موجود در جدول را که اشاره خواهد کرد را براساس قرارداد (زنجیره ای از نام جدول اشاره شده و ستون مورد نظر) انتخاب کرده اید، میتوانید ()constrained را بدون آرگمان استفاده کنید ولی اگر نام ها را بر اساس قرار داد انتخاب نکرده اید، بایستی نام جدولی که به آن اشاره میکنید را به عنوان آرگمان به ()constrained ارسال کنید.

همچنین می توانید عملکرد مورد نظر را برای ویژگی های "on delete" و " on update" محدودیت مشخص کنید.

$table->foreignId('user_id') -> constrained() -> onDelete('cascade');

ویژگی'cascade'به این معنی است که با حذف (یا به روزرسانی) ردیف parent، ستون child نیز تغییر کند و به هم وابسته باشند.

برای حذف کردن یک کلید خارجی ، می توانید از متد dropForeign استفاده کرده و محدودیت کلید خارجی را حذف کنید تا به عنوان یک آرگومان حذف شود. محدودیت های کلید خارجی از همان علامت گذاری به عنوان index استفاده می کنند ، بر اساس نام جدول و ستون های موجود در محدودیت ، و پس از آن پسوند "foreign_":

$table->dropForeign('posts_user_id_foreign');

یا می توانید یک مقدار از نوع آرایه ارسال کنید که برای حذف کلید خارجی به صورت خودکار از اسم قراردادی محدودیت کلید خارجی استفاده می کند.

$table->dropForeign(['user_id']);

با استفاده از متدهای زیر می توانید محدودیت های کلیدی خارجی را در migration خود فعال یا غیرفعال کنید:

Schema::enableForeignKeyConstraints();
Schema::disableForeignKeyConstraints();
پایگاه داده SQLite به طور پیش فرض محدودیت های کلید خارجی را غیرفعال می کند. هنگام استفاده از SQLite ، قبل از تلاش برای ایجاد آنها در migration ، اطمینان حاصل کنید که پشتیبانی کلید خارجی را در پیکربندی پایگاه داده خود فعال کنید. علاوه بر این ، SQLite تنها با ایجاد جدول از کلیدهای خارجی پشتیبانی می کند و نه هنگام تغییر جدول.

مراجع: laravel.com




phplaravelmigrationdatabase
backend developer( PHP + Laravel)
شاید از این پست‌ها خوشتان بیاید