數據庫遷移就像是數據庫的版本控制,可讓你的團隊輕鬆修改並共享應用程序的數據庫結構。遷移一般與 Laravel 的數據庫結構生成器配合使用,讓你輕鬆地構建數據庫結構。若是你曾經試過讓同事手動在數據庫結構中添加字段,那麼數據庫遷移可讓你再也不須要作這樣的事情。php
Laravel Schema
facade 對全部 Laravel 支持的數據庫系統提供了建立和操做數據表的相應支持。laravel
生成遷移
使用 Artisan 命令 make:migration
來建立遷移:數據庫
1
|
php artisan make:migration create_users_table
|
新的遷移文件會被放置在 database/migrations
目錄中。每一個遷移文件的名稱都包含了一個時間戳,以便讓 Laravel 確認遷移的順序。express
--table
和 --create
選項可用來指定數據表的名稱,或是該遷移被執行時是否將建立的新數據表。這些選項需在預生成遷移文件時填入指定的數據表:json
1
2
3
|
php artisan make:migration create_users_table --create=users
php artisan make:migration add_votes_to_users_table --table=users
|
若是你想爲生成的遷移指定一個自定義輸出路徑,則能夠在運行 make:migration
命令時添加 --path
選項。給定的路徑必須是相對於應用程序的基本路徑。數組
遷移結構
遷移類一般會包含兩個方法:up
和 down
。up
方法可爲數據庫添加新的數據表、字段或索引,而 down
方法則是 up
方法的逆操做。閉包
你能夠在這兩個方法中使用 Laravel 數據庫結構生成器來建立以及修改數據表。若要了解 Schema
生成器中的全部可用方法,可查閱它的文檔。如下的遷移實例會建立一張 flights
數據表:composer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
<?php
use
Illuminate\Support\Facades\Schema;
use
Illuminate\Database\Schema\Blueprint;
use
Illuminate\Database\Migrations\Migration;
class
CreateFlightsTable
extends
Migration
{
/**
* 運行數據庫遷移
*
* @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'
);
}
}
|
運行遷移
使用 Artisan 命令 migrate
來運行全部未完成的遷移:ide
php artisan migrate
{note} 若是你使用的是 Homestead 虛擬機,則應該在虛擬機中執行命令。post
在生產環境強制執行遷移
一些遷移操做是具備破壞性的,這意味着可能會致使數據丟失。爲了防止有人在生產環境中運行這些命令,系統會在這些命令被運行以前與你進行確認。若是要強制忽略系統的提示運行命令,則可使用 --force
標記:
1
|
php artisan migrate --force
|
回滾遷移
若要回滾最後一次遷移,可使用 rollback
命令。此命令將回滾最後一次「遷移」,其中可能包含多個遷移文件:
1
|
php artisan migrate:rollback
|
在 rollback
命令後加上 step
參數,你能夠限制回滾遷移的個數。例如,如下命令將回滾最近五次遷移:
1
|
php artisan migrate:rollback --step=5
|
migrate:reset
命令能夠回滾應用程序中的全部遷移:
1
|
php artisan migrate:reset
|
使用單個命令來執行回滾或遷移
migrate:refresh
命令不只會回滾數據庫的全部遷移還會接着運行 migrate
命令。這個命令能夠高效地重建整個數據庫:
1
|
php artisan migrate:refresh
|
// 刷新數據庫結構並執行數據填充
1
|
php artisan migrate:refresh --seed
|
使用 refresh
命令並提供 step
參數來回滾並再執行最後指定的遷移數。例如,如下命令將回滾並從新執行最後五次遷移:
1
|
php artisan migrate:refresh --step=5
|
刪除全部表 & 遷移
migrate:fresh
命令會從數據庫中刪除全部表,而後執行 migrate
命令:
1
2
3
|
php artisan migrate:fresh
php artisan migrate:fresh --seed
|
數據表
建立數據表
可使用 Schema
facade 的 create
方法來建立新的數據庫表。create
方法接受兩個參數:第一個參數爲數據表的名稱,第二個參數是 閉包
,此閉包會接收一個用於定義新數據表的 Blueprint
對象:
1
2
3
|
Schema::create(
'users'
,
function
(Blueprint
$table
) {
$table
->increments(
'id'
);
});
|
固然,在建立數據表的時候,可使用任何數據庫結構生成器的 字段方法 來定義數據表的字段。
檢查數據表或字段是否存在
可使用 hasTable
和 hasColumn
方法來檢查數據表或字段是否存在:
1
2
3
4
5
6
7
|
if
(Schema::hasTable(
'users'
)) {
//
}
if
(Schema::hasColumn(
'users'
,
'email'
)) {
//
}
|
數據庫鏈接 & 表選項
若是要對非默認鏈接的數據庫鏈接執行結構操做,可使用 connection
方法:
1
2
3
|
Schema::connection(
'foo'
)->create(
'users'
,
function
(Blueprint
$table
) {
$table
->increments(
'id'
);
});
|
你能夠在數據庫結構生成器上使用如下命令來定義表的選項:
命令 | 描述 |
---|---|
$table->engine = 'InnoDB'; |
指定表存儲引擎 (MySQL) |
$table->charset = 'utf8'; |
指定數據表的默認字符集 (MySQL) |
$table->collation = 'utf8_unicode_ci'; |
指定數據表默認的排序規則 (MySQL) |
$table->temporary(); |
建立臨時表(不支持SQL Server). |
重命名/刪除數據表
若要重命名數據表,可使用 rename
方法:
1
|
Schema::rename(
$from
,
$to
);
|
要刪除數據表,可以使用 drop
或 dropIfExists
方法:
1
2
3
|
Schema::drop(
'users'
);
Schema::dropIfExists(
'users'
);
|
重命名帶外鍵的數據表
在重命名錶以前,你應該驗證表上的任何外鍵約束在遷移文件中都有明確的名稱,而不是讓 Laravel 按照約定來設置一個名稱。不然,外鍵的約束名稱將引用舊錶名。
字段
建立字段
使用 Schema
facade 的 table
方法能夠更新現有的數據表。如同 create
方法同樣,table
方法會接受兩個參數:一個是數據表的名稱,另外一個則是接收能夠用來向表中添加字段的 Blueprint
實例的閉包
:
1
2
3
|
Schema::table(
'users'
,
function
(Blueprint
$table
) {
$table
->string(
'email'
);
});
|
可用的字段類型
數據庫結構生成器包含構建表時能夠指定的各類字段類型:
命令 | 描述 |
---|---|
$table->bigIncrements('id'); |
遞增 ID(主鍵),至關於「UNSIGNED BIG INTEGER」 |
$table->bigInteger('votes'); |
至關於 BIGINT |
$table->binary('data'); |
至關於 BLOB |
$table->boolean('confirmed'); |
至關於 BOOLEAN |
$table->char('name', 4); |
至關於帶有長度的 CHAR |
$table->date('created_at'); |
至關於 DATE |
$table->dateTime('created_at'); |
至關於 DATETIME |
$table->dateTimeTz('created_at'); |
至關於帶時區 DATETIME |
$table->decimal('amount', 8, 2); |
至關於帶有精度與基數 DECIMAL |
$table->double('column', 8, 2); |
至關於帶有精度與基數 DOUBLE |
$table->enum('level', ['easy', 'hard']); |
至關於 ENUM |
$table->float('amount', 8, 2); |
至關於帶有精度與基數 FLOAT |
$table->geometry('positions'); |
至關於 GEOMETRY |
$table->geometryCollection('positions'); |
至關於 GEOMETRYCOLLECTION |
$table->increments('id'); |
遞增的 ID (主鍵),至關於「UNSIGNED INTEGER」 |
$table->integer('votes'); |
至關於 INTEGER |
$table->ipAddress('visitor'); |
至關於 IP 地址 |
$table->json('options'); |
至關於 JSON |
$table->jsonb('options'); |
至關於 JSONB |
$table->lineString('positions'); |
至關於 LINESTRING |
$table->longText('description'); |
至關於 LONGTEXT |
$table->macAddress('device'); |
至關於 MAC 地址 |
$table->mediumIncrements('id'); |
遞增 ID (主鍵) ,至關於「UNSIGNED MEDIUM INTEGER」 |
$table->mediumInteger('votes'); |
至關於 MEDIUMINT |
$table->mediumText('description'); |
至關於 MEDIUMTEXT |
$table->morphs('taggable'); |
至關於加入遞增的 taggable_id 與字符串 taggable_type |
$table->multiLineString('positions'); |
至關於 MULTILINESTRING |
$table->multiPoint('positions'); |
至關於 MULTIPOINT |
$table->multiPolygon('positions'); |
至關於 MULTIPOLYGON |
$table->nullableMorphs('taggable'); |
至關於可空版本的 morphs() 字段 |
$table->nullableTimestamps(); |
至關於可空版本的 timestamps() 字段 |
$table->point('position'); |
至關於 POINT |
$table->polygon('positions'); |
至關於 POLYGON |
$table->rememberToken(); |
至關於可空版本的 VARCHAR(100) 的 remember_token 字段 |
$table->smallIncrements('id'); |
遞增 ID (主鍵) ,至關於「UNSIGNED SMALL INTEGER」 |
$table->smallInteger('votes'); |
至關於 SMALLINT |
$table->softDeletes(); |
至關於爲軟刪除添加一個可空的 deleted_at 字段 |
$table->softDeletesTz(); |
至關於爲軟刪除添加一個可空的 帶時區的 deleted_at 字段 |
$table->string('name', 100); |
至關於帶長度的 VARCHAR |
$table->text('description'); |
至關於 TEXT |
$table->time('sunrise'); |
至關於 TIME |
$table->timeTz('sunrise'); |
至關於帶時區的 TIME |
$table->timestamp('added_on'); |
至關於 TIMESTAMP |
$table->timestampTz('added_on'); |
至關於帶時區的 TIMESTAMP |
$table->tinyIncrements('id'); |
至關於自動遞增 UNSIGNED TINYINT |
$table->tinyInteger('votes'); |
至關於 TINYINT |
$table->unsignedBigInteger('votes'); |
至關於 Unsigned BIGINT |
$table->unsignedDecimal('amount', 8, 2); |
至關於帶有精度和基數的 UNSIGNED DECIMAL |
$table->unsignedInteger('votes'); |
至關於 Unsigned INT |
$table->unsignedMediumInteger('votes'); |
至關於 Unsigned MEDIUMINT |
$table->unsignedSmallInteger('votes'); |
至關於 Unsigned SMALLINT |
$table->unsignedTinyInteger('votes'); |
至關於 Unsigned TINYINT |
$table->uuid('id'); |
至關於 UUID |
$table->year('birth_year'); |
至關於 YEAR |
字段修飾
除了上述列出的字段類型以外,還有幾個能夠在添加字段時使用的「修飾符」。例如,若是要把字段設置爲「可空」,就使用 nullable
方法:
1
2
3
|
Schema::table(
'users'
,
function
(Blueprint
$table
) {
$table
->string(
'email'
)->nullable();
});
|
如下是全部可用的字段修飾符的列表。此列表不包括 索引修飾符:
修飾符 | 描述 |
---|---|
->after('column') |
將此字段放置在其它字段「以後」(僅限 MySQL) |
->autoIncrement() |
將 INTEGER 類型的字段設置爲自動遞增的主鍵 |
->charset('utf8') |
指定一個字符集(僅限 MySQL) |
->collation('utf8_unicode_ci') |
指定列的排序規則(僅限 MySQL/SQL Server) |
->comment('my comment') |
爲字段增長註釋(僅限 MySQL) |
->default($value) |
爲字段指定「默認」值 |
->first() |
將此字段放置在數據表的「首位」(僅限 MySQL) |
->nullable($value = true) |
(默認狀況下)此字段容許寫入 NULL 值 |
->storedAs($expression) |
建立一個存儲生成的字段 (僅限 MySQL) |
->unsigned() |
設置 integer 類型的字段爲 UNSIGNED (僅限 MySQL) |
->useCurrent() |
將 TIMESTAMP 類型的字段設置爲使用 CURRENT_TIMESTAMP 做爲默認值 |
->virtualAs($expression) |
建立一個虛擬生成的字段 (僅限 MySQL) |
修改字段
先決條件
在修改字段以前,請確保將 doctrine/dbal
依賴添加到 composer.json
文件中。Doctrine DBAL 庫用於肯定字段的當前狀態,並建立對該字段進行指定調整所需的 SQL 查詢:
composer require doctrine/dbal
更新字段屬性
change
方法能夠將現有的字段類型修改成新的類型或修改屬性。好比,你可能想增長字符串字段的長度,可使用 change
方法把 name
字段的長度從 25 增長到 50 :
1
2
3
|
Schema::table(
'users'
,
function
(Blueprint
$table
) {
$table
->string(
'name'
, 50)->change();
});
|
將字段修改成可空:
1
2
3
|
Schema::table(
'users'
,
function
(Blueprint
$table
) {
$table
->string(
'name'
, 50)->nullable()->change();
});
|
{note} 只有下面的字段類型不能被「修改」: bigInteger、binary、boolean、date、dateTime、dateTimeTz、 decimal、integer、json、longText、mediumText、smallInteger、string、text、time、unsignedBigInteger、unsignedInteger 和 unsignedSmallInteger。
重命名字段
可使用結構生成器上的 renameColumn
方法來重命名字段。在重命名字段前,請確保你的 composer.json
文件內已經加入 doctrine/dbal
依賴:
Schema::table('users', function (Blueprint $table) { $table->renameColumn('from', 'to'); });
{note} 當前不支持
enum
類型的字段重命名。
刪除字段
可使用結構生成器上的 dropColumn
方法來刪除字段。在從 SQLite 數據庫刪除字段前,你須要在 composer.json
文件中加入 doctrine/dbal
依賴並在終端執行 composer update
來安裝該依賴:
1
2
3
|
Schema::table(
'users'
,
function
(Blueprint
$table
) {
$table
->dropColumn(
'votes'
);
});
|
你能夠傳遞一個字段數組給 dropCloumn
方法來刪除多個字段:
1
2
3
|
Schema::table(
'users'
,
function
(Blueprint
$table
) {
$table
->dropColumn([
'votes'
,
'avatar'
,
'location'
]);
});
|
{note} 不支持在使用 SQLite 數據庫時在單個遷移中刪除或修改多個字段。
可用的命令別名
命令 | 描述 |
---|---|
$table->dropRememberToken(); |
刪除 remember_token 字段 |
$table->dropSoftDeletes(); |
刪除 deleted_at 字段 |
$table->dropSoftDeletesTz(); |
dropSoftDeletes() 方法的別名 |
$table->dropTimestamps(); |
刪除 created_at 和 updated_at 字段 |
$table->dropTimestampsTz(); |
dropTimestamps() 方法的別名 |
索引
建立索引
結構生成器支持多種類型的索引。首先,先指定字段值惟一,即簡單地在字段定義以後鏈式調用 unique
方法來建立索引,例如:
1
|
$table
->string(
'email'
)->unique();
|
或者,你也能夠在定義完字段以後建立索引。例如:
1
|
$table
->unique(
'email'
);
|
你甚至能夠將數組傳遞給索引方法來建立一個複合(或合成)索引:
1
|
$table
->index([
'account_id'
,
'created_at'
]);
|
Laravel 會自動生成一個合理的索引名稱,但你也能夠傳遞第二個參數來自定義索引名稱:
1
|
$table
->index(
'email'
,
'unique_email'
);
|
可用的索引類型
命令 | 描述 |
---|---|
$table->primary('id'); |
添加主鍵 |
$table->primary(['id', 'parent_id']); |
添加複合鍵 |
$table->unique('email'); |
添加惟一索引 |
$table->index('state'); |
添加普通索引 |
$table->spatialIndex('location'); |
添加空間索引( SQLite 除外) |
索引長度 & MySQL / MariaDB
Laravel 默認使用 utf8mb4
字符,它支持在數據庫中存儲「emojis」。若是你是在版本低於5.7.7 的 MySQL release 或者版本低於10.2.2 的 MariaDB release 上建立索引,那就須要你手動配置遷移生成的默認字符串長度。即在 AppServiceProvider
中調用 Schema::defaultStringLength
方法來配置它:
1
2
3
4
5
6
7
8
9
10
11
|
use
Illuminate\Support\Facades\Schema;
/**
* 引導任何應用程序服務
*
* @return void
*/
public
function
boot()
{
Schema::defaultStringLength(191);
}
|
或者,你能夠開啓數據庫的 innodb_large_prefix
選項,至於如何正確開啓,請自行查閱數據庫文檔。
刪除索引
若要移除索引,則必須指定索引的名稱。Laravel 默認會自動給索引分配合理的名稱。其將數據表名稱、索引的字段名稱及索引類型簡單地鏈接在了一塊兒。舉例以下:
命令 | 描述 |
---|---|
$table->dropPrimary('users_id_primary'); |
從「users」表中刪除主鍵。 |
$table->dropUnique('users_email_unique'); |
從「users」表中刪除惟一索引。 |
$table->dropIndex('geo_state_index'); |
從「geo」表中刪除基本索引。 |
$table->dropSpatialIndex('geo_location_spatialindex'); |
從「geo」表中刪除空間索引(SQLite除外)。 |
若是將字段數組傳遞給 dropIndex
方法,會刪除根據表名、字段和鍵類型生成的索引名稱:
1
2
3
|
Schema::table(
'geo'
,
function
(Blueprint
$table
) {
$table
->dropIndex([
'state'
]);
// 移除索引 'geo_state_index'
});
|
外鍵約束
Laravel 還支持建立用於在數據庫層中的強制引用完整性的外鍵約束。例如,讓咱們在 posts
表上定義一個引用 users
表的 id
字段的 user_id
字段:
1
2
3
4
5
|
Schema::table(
'posts'
,
function
(Blueprint
$table
) {
$table
->integer(
'user_id'
)->unsigned();
$table
->foreign(
'user_id'
)->references(
'id'
)->on(
'users'
);
});
|
還能夠爲約束的「on delete」和「on update」屬性指定所需的操做:
1
2
3
|
$table
->foreign(
'user_id'
)
->references(
'id'
)->on(
'users'
)
->onDelete(
'cascade'
);
|
你可使用 dropForeign
方法刪除外鍵。外鍵約束採用的命名方式與索引相同。即,將數據表名稱和約束的字段鏈接起來,接着加上「_foreign」後綴:
1
|
$table
->dropForeign(
'posts_user_id_foreign'
);
|
或者,你也能夠傳遞一個字段數組,在刪除的時候會按照約定自動轉換爲對應的外鍵名稱:
1
|
$table
->dropForeign([
'user_id'
]);
|
你能夠在遷移文件裏使用如下方法來開啓或關閉外鍵約束:
1
2
3
|
Schema::enableForeignKeyConstraints();
Schema::disableForeignKeyConstraints();
|
本文轉載而來!本文連接來源於 https://laravel-china.org/docs/laravel/5.5/migrations/1329#generating-migrations