NỘI DUNG
Migration được coi như là version control cho database, cho phép team có thể dễ dàng thay đổi và chia sẻ schema của database trong chương trình với nhau. Migratiom cơ bản được sử dụng cùng với schema builder để dễ dàng xây dựng cấu trúc cho database schema. Nếu bạn đã gặp vấn đề khi thêm một cột vào local của các đồng đội trong team, migration sẽ xử lý vấn đề này rất dễ dàng. Schema facade hỗ trợ việc tạo và thao tác trên các bảng mà không cần biết về database, tương ứng và mạch lạc khi giao tiếp với các hệ thống database khác nhau mà Laravel hỗ trợ.
Tạo Migrations
Để tạo một migration, sử dụng câu lệnh make:migration
Artisan:
php artisan make:migration create_users_table
File migration mới sẽ được đặt trong thư mục database/migrations
. Mỗi file migration được đặt tên bao gồm timestamp để xác định thứ tự các migration với nhau.
Tham số --table
và --create
có thể được sử dụng để cho biết table nào và migration có cần tạo table mới hay không. Hai tham số này đơn giản được dùng để cho mã stub được tạo ra sẽ thực hiện trên table nào:
php artisan make:migration create_users_table --create=users
php artisan make:migration add_votes_to_users_table --table=users
Nếu bạn muốn đưa migration vào trong một thư mục khác, bạn có thể truyền vào tham số --path
khi thực hiện lệnh make:migration
. Đường dẫn đưa vào phải relative với đường dẫn cơ bản của chương trình.
Cấu trúc migration
Một migration class chứa hai hàm cơ bản là: up
và down
. Hàm up
được dùng để tạo table, cột hay index mới vào trong database, trong khi hàm down
đơn giản chỉ dùng để làm ngược lại những thao tác ở hàm up
.
Bên trong hai hàm này bạn có thể sử dụng schema builder để tạo và chỉnh sửa table rõ ràng hơn. Để tìm hiểu tất cả các hàm được cung cấp trong Schema
builder. Ví dụ, hãy cùng nhau làm một ví dụ về migration bằng việc tạo ra một bảng tên là flights
:
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateFlightsTable extends Migration
{
public function up()
{
Schema::create('flights', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('airline');
$table->timestamps();
});
}
public function down()
{
Schema::drop('flights');
}
}
Thực thi Migrations
Để thực thi tất cả các migration trong chương trình, sử dụng lệnh migrate
Artisan:
php artisan migrate
Nếu bạn đang sử dụng Homestead virtual machine, bạn cần chạy câu lệnh này bên trong đó.
Ép buộc thực thi migration chạy cho môi trường production
Một số thao tác migration khá là nguy hiểm, vì chúng có thể gây ra mất mát dữ liệu. Để tránh khỏi điều này khi thực thi các câu lệnh migration trong môi trường production, bạn sẽ nhận được yêu cầu xác nhận trước khi thực chi chúng. Để ép các câu lệnh này thực thi mà không cần xác nhận, sử dụng cờ --force
:
php artisan migrate --force
Rolling Back Migrations
Để rollback lại thao tác migration cuối cùng, bạn có thể sử dụng câu lệnh rollback
. Lệnh sẽ rolls back lại row có “batch” lớn nhất của bảng migrations, có thể bao gồm một hoặc nhiều file migration:
php artisan migrate:rollback
Bạn có thế giới hạn số file migrations rollback bằng thêm step
vào lệnh rollback
. Ví dụ, lệnh sau sẽ rollback 5 file sau cùng của bảng migrations có “batch” lớn nhất:
php artisan migrate:rollback --step=5
Lệnh migrate:reset
sẽ thực hiện rollback lại toàn bộ migration của chương trình:
php artisan migrate:reset
Rollback & Migrate trong một câu lệnh
Lệnh migrate:refresh
sẽ đầu tiên rollback lại toàn bộ migration của chương trình, và thực hiện câu lệnh migrate
. Câu lệnh sẽ thực hiện tái cấu trúc toàn bộ database:
php artisan migrate:refresh
php artisan migrate:refresh --seed
Bạn có thẻ rollback & migrate lại với giới hạn migrations bởi cờ step
vào lệnh refresh
. Ví dụ, lệnh sau sẽ rollback & migrate lại 5 file mới nhất của migrations:
php artisan migrate:refresh --step=5
Bảng
Tạo bảng
Để tạo một bảng mới, sử dụng hàm create
trong Schema
facade. Hàm create
nhận hai tham số. Tham số đầu là tên của bảng, còn tham số thứ hai là một Closure
mà sẽ nhận vào một Blueprint
object để khai báo cấu trúc của bảng mới:
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
});
Tất nhiên, Khi tạo bảng mới, bạn có thể sử dụng bất cứ hàm tạo cột nào để tạo các trường cho bảng.
Kiểm tra xem bảng hay cột có tồn tại hay không
Bạn có thể dễ dàng kiểm tra sự tồn tại của một bảng hay cột sử dụng hàm hasTable
and hasColumn
:
if (Schema::hasTable('users')) {
//
}
if (Schema::hasColumn('users', 'email')) {
//
}
Connection & Storage Engine
Nếu bạn muốn thực hiện thao tác schema trên một kết nối database không phải mặc định, sử dụng hàm connection
:
Schema::connection('foo')->create('users', function ($table) {
$table->increments('id');
});
Bạn có thể sử dụng thuộc tính engine
trên schema builder để định nghĩa storage engine cho bảng:
Schema::create('users', function ($table) {
$table->engine = 'InnoDB';
$table->increments('id');
});
Đổi tên / xóa bảng
Để đổi tên một bảng đã tồn tại trong database, sử dụng hàm rename
:
Schema::rename($from, $to);
Để drop một bảng trong database, bạn có thể sử dụng hàm drop
hoặc dropIfExists
:
Schema::drop('users');
Schema::dropIfExists('users');
Đổi tên bảng với foreign keys
Trước khi thay đổi tên bảng, bạn nên kiểm tra xem có foreign key constraints nào trên bảng có tên khác trong migration file hay không thay vì để Laravel tự gán tên. Nếu không, tên của foreign key constraint sẽ trỏ tới tên cũ của bảng.
Columns
Tạo Columns
Hàm table
trong Schema
facade sử dụng để cập nhật một bảng đã tồn tại. Như hàm create
, hàm table
nhận hai tham số: tên của bảng và một Closure
nhận một Blueprint
object để thực hiện thao tác với table:
Schema::table('users', function ($table) {
$table->string('email');
});
Các kiểu Column
Tất nhiên, the schema builder chứa vài kểu column cho bạn có thể khi tạo bảng:
Command | Description |
---|---|
$table->bigIncrements('id'); |
Tăng ID (primary key) sư dụng như “UNSIGNED BIG INTEGER”. |
$table->bigInteger('votes'); |
Tương đương với BIGINT. |
$table->binary('data'); |
Tương đương với BLOB. |
$table->boolean('confirmed'); |
Tương đương với BOOLEAN. |
$table->char('name', 4); |
Tương đương với CHAR với độ dài cho trước. |
$table->date('created_at'); |
Tương đương với DATE. |
$table->dateTime('created_at'); |
Tương đương với DATETIME. |
$table->dateTimeTz('created_at'); |
Tương đương với DATETIME (with timezone). |
$table->decimal('amount', 5, 2); |
Tương đương với DECIMAL với độ chính sách và phần thập phân. |
$table->double('column', 15, 8); |
Tương đương với DOUBLE với độ chính xác, 15 chữ số và 8 ký tự tính sau dấu phảy. |
$table->enum('choices', ['foo', 'bar']); |
Tương đương với ENUM. |
$table->float('amount', 8, 2); |
Tương đương với FLOAT, 8 chữ số and 2 chữ số tính sau dấu phẩy. |
$table->increments('id'); |
Tăng ID (primary key) sử dụng như “UNSIGNED INTEGER”. |
$table->integer('votes'); |
Tương đương với INTEGER. |
$table->ipAddress('visitor'); |
Tương đương với IP. |
$table->json('options'); |
Tương đương với JSON. |
$table->jsonb('options'); |
Tương đương với JSONB. |
$table->longText('description'); |
Tương đương với LONGTEXT. |
$table->macAddress('device'); |
Tương đương với MAC. |
$table->mediumIncrements('id'); |
Tăng ID (primary key) sử dụng như “UNSIGNED MEDIUM INTEGER”. |
$table->mediumInteger('numbers'); |
Tương đương với MEDIUMINT. |
$table->mediumText('description'); |
Tương đương với MEDIUMTEXT. |
$table->morphs('taggable'); |
Thêm unsigned INTEGER taggable_id và STRING taggable_type . |
$table->nullableTimestamps(); |
Giống như timestamps() . |
$table->rememberToken(); |
Thêm remember_token như VARCHAR(100) NULL. |
$table->smallIncrements('id'); |
Tăng ID (primary key) sử dụng như “UNSIGNED SMALL INTEGER”. |
$table->smallInteger('votes'); |
Tương đương với SMALLINT. |
$table->softDeletes(); |
Thêm nullable deleted_at column for soft deletes. |
$table->string('email'); |
Tương đương với VARCHAR . |
$table->string('name', 100); |
Tương đương với VARCHAR với độ dài. |
$table->text('description'); |
Tương đương với TEXT. |
$table->time('sunrise'); |
Tương đương với TIME. |
$table->timeTz('sunrise'); |
Tương đương với TIME (với timezone). |
$table->tinyInteger('numbers'); |
Tương đương với TINYINT. |
$table->timestamp('added_on'); |
Tương đương với TIMESTAMP. |
$table->timestampTz('added_on'); |
Tương đương với TIMESTAMP (với timezone). |
$table->timestamps(); |
Thêm nullable created_at và cột updated_at . |
$table->timestampsTz(); |
Thêm nullable created_at và updated_at (với timezone). |
$table->unsignedBigInteger('votes'); |
Tương đương với Unsigned BIGINT. |
$table->unsignedInteger('votes'); |
Tương đương với Unsigned INT. |
$table->unsignedMediumInteger('votes'); |
Tương đương với Unsigned MEDIUMINT. |
$table->unsignedSmallInteger('votes'); |
Tương đương với Unsigned SMALLINT. |
$table->unsignedTinyInteger('votes'); |
Tương đương với Unsigned TINYINT. |
$table->uuid('id'); |
Tương đương với UUID. |
Column Modifiers
Ngoài các kiểu column liệt kê ở trên, có một số kiểu column “modifiers” khác mà bạn có thể sử dụng. Ví dụ để làm cho column “nullable”, bạn có thể dùng hàm nullable
:
Schema::table('users', function ($table) {
$table->string('email')->nullable();
});
Dưới đây là một số column modifier mà bạn có thể sử dụng, không bao gồm các index modifiers:
Modifier | Description |
---|---|
->after('column') |
Đặt column “after” một column khác (MySQL Only) |
->comment('my comment') |
Thêm một comment cho column. |
->default($value) |
Đặt giá trị “mặc định” vào column |
->first() |
Đặt column “first” vào trong bảng (MySQL Only) |
->nullable() |
Cho phép dữ liệu kiểu NULL có thể chèn vào column. |
->storedAs($expression) |
Tạo một cột stored (MySQL Only) |
->unsigned() |
Đặt cột integer sang UNSIGNED |
->virtualAs($expression) |
Tạo một cột virtual (MySQL Only) |
Modifying Columns
Yêu cầu
Trước khi chỉnh sửa column, hãy chắc chắn là bạn thêm vào doctrine/dbal
dependency vào trong file composer.json
. Thư viện Doctrine DBAL được dùng để xác định trạng thái hiện tại của column và tạo câu SQL query cần thiết để chỉnh sửa column:
composer require doctrine/dbal
Cập nhật thuộc tính của Column
Hàm change
cho phép bạn thay đổi một column sang một kiểu mới, hoặc thay đổi thuộc tính của column. Ví dụ, bạn có thể muốn tăng kích thước của string. Xem ví dụ dưới đây trong việc sử dụng change
để thay đổi kích thước của column name
column từ 25 thành 50:
Schema::table('users', function ($table) {
$table->string('name', 50)->change();
});
Chúng ta cũng có thể thay đổi một column sang nullable:
Schema::table('users', function ($table) {
$table->string('name', 50)->nullable()->change();
});
Đổi tên columns
Để thay đổi tên column, bạn có thể sử dụng hàm renameColumn
trong Schema builder. Trước khi đổi tên một column, hãy chắc chắn rằng đã thêm doctrine/dbal
dependency vào file composer.json
:
Schema::table('users', function ($table) {
$table->renameColumn('from', 'to');
});
Dropping Columns
Để drop một column, sử dụng hàm dropColumn
trong the Schema builder. Trước khi dropping columns từ SQLite database, bạn cần phải thêm doctrine/dbal
dependency vào file composer.json
và chạy lệnh composer update
để cài thư viện:
Schema::table('users', function ($table) {
$table->dropColumn('votes');
});
Bạn có thể drop nhiều columns từ một bảng bằng cách truyền một mảng các tên column vào hàm dropColumn
:
Schema::table('users', function ($table) {
$table->dropColumn(['votes', 'avatar', 'location']);
});
Indexes
Tạo Indexes
Schema builder hỗ trợ vài kiểu index. Đầu tiên, cùng xem một ví dụ tạo column có giá trị là unique. Để tạo index, chúng ta sẽ sử dụng hàm unique
khi tạo column:
$table->string('email')->unique();
Ngoài ra bạn có thể tạo index ngay sau khi tạo column, ví dụ:
$table->unique('email');
Bạn có thể truyền vào một mảng column cho hàm :
$table->index(['account_id', 'created_at']);
Laravel sẽ tự thực hiện tạo tên phù hợp cho index, nhưng bạn có thể tự đặt tên cho index bằng cách truyền vào tham số thứ hai:
$table->index('email', 'my_index_name');
Các kiểu Index
Command | Description |
---|---|
$table->primary('id'); |
Thêm vào một primary key. |
$table->primary(['first', 'last']); |
Thêm vào một composite keys. |
$table->unique('email'); |
Thêm vào một unique index. |
$table->unique('state', 'my_index_name'); |
Thêm một index có tên. |
$table->index('state'); |
Thêm vào một index. |
Dropping Indexes
Để drop một index, bạn cần truyền vào tên của index. Về mặc định, Laravel sẽ tự động gán một tên phù hợp cho index. Đơn giản chỉ là nối tên bảng, tên của column được index và kiểu index. Dưới đây là một vài ví dụ:
Command | Description |
---|---|
$table->dropPrimary('users_id_primary'); |
Drop một primary key khỏi bảng “users”. |
$table->dropUnique('users_email_unique'); |
Drop một unique key khỏi bảng “users”. |
$table->dropIndex('geo_state_index'); |
Drop một unique key khỏi bảng “geo”. |
Nếu bạn truyền vào một mảng các column, thì Laravel sẽ thực hiện tìm tên index tương ứng dựa theo quy tắc đặt để drop:
Schema::table('geo', function ($table) {
$table->dropIndex(['state']); // Drops index 'geo_state_index'
});
Foreign Key Constraints
Laravel cũng hỗ trợ cung cấp việc tạo foreign key constraint một cách dễ dàng. Ví dụ, cùng tạo một column user_id
trong bảng posts
tham chiếu tới column id
trong bảng users
:
Schema::table('posts', function ($table) {
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
});
Bạn cũng có thể chỉ định thao tác cho thuộc tính “on delete” và “on update” của constraint:
$table->foreign('user_id')
->references('id')->on('users')
->onDelete('cascade');
Để drop một foreign key, bạn có thể sử dụng hàm dropForeign
. Foreign key constraints sử dụng chung quy tắc đặt tên như index. Vì thế, chúng ta tên của foreign key constraints sẽ bao gồm tên bảng, tên cột và hậu tố là “_foreign”:
$table->dropForeign('posts_user_id_foreign');
Hay bạn có thể truyền vào một mảng các giá trị để thực hiện drop theo quy tắc đặt tên:
$table->dropForeign(['user_id']);
Bạn có thể kích hoạt hay bỏ kích hoạt việc sử dụng foreign key constraint trong migration sử dụng hai hàm sau:
Schema::enableForeignKeyConstraints();
Schema::disableForeignKeyConstraints();