遷移,遷移通常和Laravel的結(jié)構(gòu)構(gòu)建器結(jié)對(duì)從而可以很容易地構(gòu)建應(yīng)用的數(shù)據(jù)庫表結(jié)構(gòu)。
Laravel的Schema
門面提供了與數(shù)據(jù)庫系統(tǒng)無關(guān)的創(chuàng)建和操縱表的支持,在Laravel所支持的所有數(shù)據(jù)庫系統(tǒng)中提供一致的、優(yōu)雅的、平滑的API。
使用Artisan命令make:migration
來創(chuàng)建一個(gè)新的遷移:
php artisan make:migration create_users_table
新的遷移位于database/migrations
目錄下,每個(gè)遷移文件名都包含時(shí)間戳從而允許Laravel判斷其順序。
--table
和--create
選項(xiàng)可以用于指定表名以及該遷移是否要?jiǎng)?chuàng)建一個(gè)新的數(shù)據(jù)表。這些選項(xiàng)只需要簡單放在上述遷移命令后面并指定表名:
php artisan make:migration add_votes_to_users_table --table=users
php artisan make:migration create_users_table --create=users
如果你想要指定生成遷移的自定義輸出路徑,在執(zhí)行make:migration
命令時(shí)可以使用--path
選項(xiàng),提供的路徑應(yīng)該是相對(duì)于應(yīng)用根目錄的。
遷移類包含了兩個(gè)方法:up
和down
。up
方法用于新增表,列或者索引到數(shù)據(jù)庫,而down
方法就是up
方法的反操作,和up
里的操作相反。
在這兩個(gè)方法中你都要用到Laravel的表結(jié)構(gòu)構(gòu)建器來創(chuàng)建和修改表,想要學(xué)習(xí)Schema
構(gòu)建器的更多有用方法,可以查看其文檔。例如,讓我們先看看創(chuàng)建flights
表的簡單示例:
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateFlightsTable extends Migration{
/**
* 運(yùn)行遷移
*
* @return void
*/
public function up()
{
Schema::create('flights', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('airline');
$table->timestamps();
});
}
/**
* 撤銷遷移
*
* @return void
*/
public function down()
{
Schema::drop('flights');
}
}
要運(yùn)行應(yīng)用中所有未執(zhí)行的遷移,可以使用Artisan命令的migrate
方法。如果你正在使用Homestead虛擬機(jī),應(yīng)該在你的虛擬機(jī)中運(yùn)行如下這條命令:
php artisan migrate
如果再運(yùn)行時(shí)遇到”class not found“的錯(cuò)誤提示,嘗試運(yùn)行composer dump-autoload
命令然后重新運(yùn)行遷移命令。
在生產(chǎn)環(huán)境中強(qiáng)制運(yùn)行遷移
有些遷移操作是毀滅性的,這意味著它們可能造成數(shù)據(jù)的丟失,為了避免在生產(chǎn)環(huán)境數(shù)據(jù)庫中運(yùn)行這些命令,你將會(huì)在運(yùn)行這些命令之前被提示并確認(rèn)。想要強(qiáng)制運(yùn)行這些命令而不被提示,可以使用--force
:
php artisan migrate --force
想要回滾最新的一次遷移”操作“,可以使用rollback
命令,注意這將會(huì)回滾最后一批運(yùn)行的遷移,可能包含多個(gè)遷移文件:
php artisan migrate:rollback
migrate:reset
命令將會(huì)回滾所有的應(yīng)用遷移:
php artisan migrate:reset
migrate:refresh
命令將會(huì)先回滾所有數(shù)據(jù)庫遷移,然后運(yùn)行migrate
命令。這個(gè)命令可以有效的重建整個(gè)數(shù)據(jù)庫:
php artisan migrate:refresh
php artisan migrate:refresh --seed
使用Schema
門面上的create
方法來創(chuàng)建新的數(shù)據(jù)表。create
方法接收兩個(gè)參數(shù),第一個(gè)是表名,第二個(gè)是獲取用于定義新表的Blueprint
對(duì)象的閉包:
Schema::create('users', function ($table) {
$table->increments('id');
});
當(dāng)然,創(chuàng)建新表的時(shí)候,可以使用表結(jié)構(gòu)構(gòu)建器中的任意列方法來定義數(shù)據(jù)表的列。
你可以輕松地使用hasTable和hasColumn方法檢查表或列是否存在:
if (Schema::hasTable('users')) {
//
}
if (Schema::hasColumn('users', 'email')) {
//
}
如果你想要在一個(gè)數(shù)據(jù)庫連接上執(zhí)行表結(jié)構(gòu)操作,該數(shù)據(jù)庫連接并不是默認(rèn)數(shù)據(jù)庫連接,使用connection
方法:
Schema::connection('foo')->create('users', function ($table) {
$table->increments('id');
});
要設(shè)置表的存儲(chǔ)引擎,在表結(jié)構(gòu)構(gòu)建器上設(shè)置engine
屬性:
Schema::create('users', function ($table) {
$table->engine = 'InnoDB';
$table->increments('id');
});
要重命名一個(gè)已存在的數(shù)據(jù)表,使用rename
方法:
Schema::rename($from, $to);
要?jiǎng)h除一個(gè)已存在的數(shù)據(jù)表,可以使用drop
或dropIfExists
方法:
Schema::drop('users');Schema::dropIfExists('users');
要更新一個(gè)已存在的表,使用Schema門面上的table
方法,和create
方法一樣,table
方法接收兩個(gè)參數(shù):表名和獲取用于添加列到表的Blueprint
實(shí)例的閉包:
Schema::table('users', function ($table) {
$table->string('email');
});
當(dāng)然,表結(jié)構(gòu)構(gòu)建器包含一系列你可以用來構(gòu)建表的列類型:
命令 | 描述 |
---|---|
$table->bigIncrements('id'); |
自增ID,類型為bigint |
$table->bigInteger('votes'); |
等同于數(shù)據(jù)庫中的BIGINT類型 |
$table->binary('data'); |
等同于數(shù)據(jù)庫中的BLOB類型 |
$table->boolean('confirmed'); |
等同于數(shù)據(jù)庫中的BOOLEAN類型 |
$table->char('name', 4); |
等同于數(shù)據(jù)庫中的CHAR類型 |
$table->date('created_at'); |
等同于數(shù)據(jù)庫中的DATE類型 |
$table->dateTime('created_at'); |
等同于數(shù)據(jù)庫中的DATETIME類型 |
$table->decimal('amount', 5, 2); |
等同于數(shù)據(jù)庫中的DECIMAL類型,帶一個(gè)精度和范圍 |
$table->double('column', 15, 8); |
等同于數(shù)據(jù)庫中的DOUBLE類型,帶精度, 總共15位數(shù)字,小數(shù)點(diǎn)后8位. |
$table->enum('choices', ['foo', 'bar']); |
等同于數(shù)據(jù)庫中的?ENUM類型 |
$table->float('amount'); |
等同于數(shù)據(jù)庫中的?FLOAT?類型 |
$table->increments('id'); |
數(shù)據(jù)庫主鍵自增ID |
$table->integer('votes'); |
等同于數(shù)據(jù)庫中的?INTEGER?類型 |
$table->json('options'); |
等同于數(shù)據(jù)庫中的?JSON?類型 |
$table->jsonb('options'); |
等同于數(shù)據(jù)庫中的 JSONB?類型 |
$table->longText('description'); |
等同于數(shù)據(jù)庫中的 LONGTEXT?類型 |
$table->mediumInteger('numbers'); |
等同于數(shù)據(jù)庫中的?MEDIUMINT類型 |
$table->mediumText('description'); |
等同于數(shù)據(jù)庫中的?MEDIUMTEXT類型 |
$table->morphs('taggable'); |
添加一個(gè) INTEGER類型的?taggable_id ?列和一個(gè) STRING類型的?taggable_type 列 |
$table->nullableTimestamps(); |
和?timestamps() 一樣但不允許 NULL值. |
$table->rememberToken(); |
添加一個(gè)?remember_token ?列: VARCHAR(100) NULL. |
$table->smallInteger('votes'); |
等同于數(shù)據(jù)庫中的?SMALLINT?類型 |
$table->softDeletes(); |
新增一個(gè)?deleted_at ?列?用于軟刪除. |
$table->string('email'); |
等同于數(shù)據(jù)庫中的?VARCHAR?列??. |
$table->string('name', 100); |
等同于數(shù)據(jù)庫中的?VARCHAR,帶一個(gè)長度 |
$table->text('description'); |
等同于數(shù)據(jù)庫中的?TEXT 類型 |
$table->time('sunrise'); |
等同于數(shù)據(jù)庫中的?TIME類型 |
$table->tinyInteger('numbers'); |
等同于數(shù)據(jù)庫中的?TINYINT?類型 |
$table->timestamp('added_on'); |
等同于數(shù)據(jù)庫中的?TIMESTAMP 類型 |
$table->timestamps(); |
添加?created_at ?和?updated_at 列. |
除了上面列出的列類型之外,在添加列的時(shí)候還可以使用一些其它列”修改器“,例如,要使列默認(rèn)為null,可以使用nullable
方法:
Schema::table('users', function ($table) {
$table->string('email')->nullable();
});
下面是所有可用的列修改器列表,該列表不包含索引修改器:
修改器 | 描述 |
---|---|
->first() |
將該列置為表中第一個(gè)列 (僅適用于MySQL) |
->after('column') |
將該列置于另一個(gè)列之后 (僅適用于MySQL) |
->nullable() |
允許該列的值為NULL |
->default($value) |
指定列的默認(rèn)值 |
->unsigned() |
設(shè)置?integer ?列為?UNSIGNED |
在修改列之前,確保已經(jīng)將doctrine/dbal
依賴添加到composer.json
文件,Doctrine DBAL庫用于判斷列的當(dāng)前狀態(tài)并在需要時(shí)創(chuàng)建SQL查詢來對(duì)列進(jìn)行指定的調(diào)整。
change
方法允許你修改已存在的列為新的類型,或者修改列的屬性。例如,你可能想要增加string類型列的尺寸,讓我們將name
列的尺寸從25增加到50:
Schema::table('users', function ($table) {
$table->string('name', 50)->change();
});
我們還可以修改該列允許NULL值:
Schema::table('users', function ($table) {
$table->string('name', 50)->nullable()->change();
});
要重命名一個(gè)列,可以使用表結(jié)構(gòu)構(gòu)建器上的renameColumn
方法,在重命名一個(gè)列之前,確保doctrine/dbal
依賴已經(jīng)添加到composer.json
文件:
Schema::table('users', function ($table) {
$table->renameColumn('from', 'to');
});
注意:enum類型的列的重命名暫不支持。
要?jiǎng)h除一個(gè)列,使用表結(jié)構(gòu)構(gòu)建器上的dropColumn
方法:
Schema::table('users', function ($table) {
$table->dropColumn('votes');
});
你可以傳遞列名數(shù)組到dropColumn
方法從表中刪除多個(gè)列:
Schema::table('users', function ($table) {
$table->dropColumn(['votes', 'avatar', 'location']);
});
注意:在從SQLite數(shù)據(jù)庫刪除列之前,需要添加
doctrine/dbal
依賴到composer.json
文件并在終端中運(yùn)行composer update
命令來安裝該庫。
表結(jié)構(gòu)構(gòu)建器支持多種類型的索引,首先,讓我們看一個(gè)指定列值為唯一索引的例子。要?jiǎng)?chuàng)建索引,可以使用unique
方法:
$table->string('email')->unique();
此外,你可以在定義列之后創(chuàng)建索引,例如:
$table->unique('email');
你甚至可以傳遞列名數(shù)組到索引方法來創(chuàng)建混合索引:
$table->index(['account_id', 'created_at']);
命令 | 描述 |
---|---|
$table->primary('id'); |
添加主鍵索引 |
$table->primary(['first', 'last']); |
添加混合索引 |
$table->unique('email'); |
添加唯一索引 |
$table->index('state'); |
添加普通索引 |
要?jiǎng)h除索引,必須指定索引名。默認(rèn)情況下,Laravel自動(dòng)分配適當(dāng)?shù)拿Q給索引——簡單連接表名、列名和索引類型。下面是一些例子:
命令 | 描述 |
---|---|
$table->dropPrimary('users_id_primary'); |
從?“users”表中刪除主鍵索引 |
$table->dropUnique('users_email_unique'); |
從?“users”表中刪除唯一索引 |
$table->dropIndex('geo_state_index'); |
從?“geo”表中刪除普通索引 |
Laravel還提供了創(chuàng)建外鍵約束的支持,用于在數(shù)據(jù)庫層面強(qiáng)制引用完整性。例如,我們?cè)?code>posts表中定義了一個(gè)引用users
表的id
列的user_id
列:
Schema::table('posts', function ($table) {
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
});
你還可以為約束的“on delete”和“on update”屬性指定期望的動(dòng)作:
$table->foreign('user_id')
->references('id')->on('users')
->onDelete('cascade');
要?jiǎng)h除一個(gè)外鍵,可以使用dropForeign
方法。外鍵約束和索引使用同樣的命名規(guī)則——連接表名、外鍵名然后加上”_foreign”后綴:
$table->dropForeign('posts_user_id_foreign');
更多建議: