تصور کنید می خواهید یک پروژه لاراول را با دوستانتان توسعه دهید، برای این کار علاوه بر استفاده اشتراکی از کد های پروژه، میبایست طرحواره پایگاه داده ی پروژه را نیز با یکدیگر به اشتراک بگذارید! حال فرض کنید یکی از هم تیمی های شما قصد در ایجاد یک ستون در یک جدول در پایگاه داده دارد، برای اینکه در ادامه روند پروژه شما مشکلی پیش نیاید و تمام اعضای گروه آخرین نسخه به روز طرحواره پایگاه داده را داشته باشند، تمام اعضای گروه باید آن ستون را با همان نام و در همان جدول به صورت دستی ایجاد کنند. این همه کار فقط برای ایجاد یک ستون!!!
این مشکل را لاراول با استفاده از migration ها حل کرده است. در ادامه بیشتر با migration ها آشنا می شویم:
اگر با لاراول آشنا باشید قطعا با دستورات php artisan آشنایی دارید!
برای ساخت یک migration از دستور
استفاده میکنیم. migration ایجاد شده در مسیر database/migrations قرار دارد.
با توجه به راهنمایی تصویر بالا میتوان از این دستور استفاده کرد. برای مثال برای ساخت یک جدول به نام users ،از دستور
استفاده میکنیم. در دستور بالا به چند نکته باید توجه کرد:
1)قبل از قسمت options ما timestamp را create_users_table نام گذاری کردیم. این نام گذاری اختیاریست ولی بهتر است نام مناسب (قراردادی) در نظر بگیرید.
2)اگر از قبل جدول users را دارید و فقط میخواهید اطلاعاتی را به آن migrateکنید بهتر است به جای create - - از table - - استفاده کنید.
3)همان طور که گفته شد این فایل به طور پیش فرض در مسیر database/migrations ایجاد خواهد شد ولی اگر بخواهید مسیر آن را تغییر دهید میتوانید از path - - استفاده کنید. توجه داشته باشد که مسیر تعیین شده بایستی نسبت به مسیر پایه اپلیکیشن تعیین شود.
یک کلاس migration دارای 2 متد up و down می باشد. که متد up برای افزودن جدول ها یا ستون ها و یا index های جدید در پایگاه داده استفاده می شود. و متد down معکوس متد up بوده و عملیات انجام گرفته توسط این متد را به عقب برمیگرداند. در هر 2 متد میتوان از سازنده طرحواره(schema builder) استفاده کرد.
برای مثال در قطعه کد زیر نحوه ایجاد جدول users را با تعدادی ستون مشاهده میکنید. (البته توجه داشته باشید که این قطعه کد را داخل فایل migration ایجاد شده با دستور
قرار میدهیم.)
<?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 های موجود در database/migrations میبایست دستور
را در خط فرمان اجرا کنیم. که ترتیب اجرای این migration ها بر اساس timestamp های آن ها خواهد بود(تاریخ و ساعتی که موقع ایجاد، لاراول برای آن ها در نظر میگیرد).
اجرای migration تحت هر شرایطی در مرحله ی production:
برخی از عملیات migration مخرب است ، به این معنی که ممکن است باعث از بین رفتن اطلاعات شما شود. برای اینکه از اجرای این دستورات در برابر پایگاه داده در محیط production محافظت کنید ، قبل از اجرای دستورات از شما خواسته می شود تا تأیید کنید. برای مجبور کردن دستورات بدون درخواست تایید، از force - - استفاده کنید. php artisan migrate - - force
برای برگرداندن آخرین عملیات migration ، می توانید از دستور برگشت استفاده کنید. این دستور آخرین دسته migration ها را برمیگرداند ، که ممکن است شامل چند فایل migartion باشد:
برای بازگرداندن تمام migration های اپلیکشن خود، میتوانید از دستور تنظیم مجدد استفاده کنید.
برای بازگرداندن و اجرای مجدد تمام migration در یک دستور از دستور refresh استفاده میکنیم.
برای حذف و اجرای مجدد تمام migration ها در یک دستور میتوان از دستور fresh استفاده کرد.
برای بازگرداندن تعداد محدودی از migration ها میتوانید از step - - استفاده کنید. برای مثال برای بازگرداندن 2 ،migration آخر از دستور
استفاده میکنیم. این گزینه برای تمام دستورات برگشت صادق است.
توجه کنید که با اجرای این دستورها اطلاعات ثبت شده در جدول های بازگردانده شده حذف میشود. بنابراین برای ساخت دوباره اطلاعات داخل جدول از 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برای تعریف گزینه های جدول استفاده کنید:
$table->engine = 'InnoDB';
$table->charset = 'utf8mb4';
$table->collation = 'utf8mb4_unicode_ci';
$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->id();
$table->foreignId('user_id');
$table->bigIncrements('id');
$table->bigInteger('votes');
$table->binary('data');
$table->boolean('confirmed');
$table->char('name', 100);
$table->date('created_at');
$table->decimal('amount', 8, 2);
$table->double('amount', 8, 2);
$table->enum('level', ['easy', 'hard']);
$table->float('amount', 8, 2);
$table->increments('id');
$table->integer('votes');
$table->ipAddress('visitor');
$table->json('options');
$table->jsonb('options');
$table->longText('description');
$table->rememberToken();
$table->string('name', 100);
$table->text('description');
$table->timestamps(0);
لیست کامل این ستون ها را میتوانید از Laravel.com مطالعه فرمایید.
اصلاح کنندگان ستون
علاوه بر انواع ستون های ذکر شده در بالا ، چندین تغییر دهنده ستون وجود دارد که می توانید هنگام افزودن ستون به جدول پایگاه داده از آنها استفاده کنید. برای مثال ، برای ساختن ستون "nullable" ، می توانید از متد nullable استفاده کنید.
Schema::table('users', function(Blueprint $table){ $table->string('email')->nullable(); });
در زیر لیستی از برخی column modifier های موجود را مشاهده می کنید. در این لیست index modifier ها لحاظ نشده است.
->autoIncrement()
->charset('utf8mb4')
->default($value)
->nullable($value = true)
->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']); });
ساخت فهرست
سازنده طرحواره 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');
$table->primary(['id', 'parent_id']);
$table->unique('email');
$table->index('state');
$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 را بر اساس نام جدول ، نام ستون فهرست شده و نوع فهرست اختصاص می دهد(اسم جدول، اسم ستون فهرست شده و نوع آن فهرست را به صورت زنجیره ای به هم متصل می کند). در اینجا چند مثال آورده شده است.
$table->dropPrimary('users_id_primary');
$table->dropUnique('users_email_unique');
$table->dropIndex('geo_state_index');
$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