跳到內容

資料庫:遷移

簡介

遷移就像是資料庫的版本控制,讓您的團隊可以定義和分享應用程式的資料庫結構定義。如果您曾經需要告訴隊友在從原始碼控制拉取您的變更後,手動將資料行新增到他們的本機資料庫結構中,那麼您就遇到了資料庫遷移要解決的問題。

Laravel Schema facade 提供了資料庫不可知的支援,用於在所有 Laravel 支援的資料庫系統中建立和操作資料表。通常,遷移會使用此 facade 來建立和修改資料庫資料表和資料行。

產生遷移

您可以使用 make:migration Artisan 命令 來產生資料庫遷移。新的遷移將放置在您的 database/migrations 目錄中。每個遷移檔案名稱都包含一個時間戳記,讓 Laravel 可以判斷遷移的順序

1php artisan make:migration create_flights_table

Laravel 將使用遷移的名稱來嘗試猜測資料表的名稱,以及遷移是否將建立新的資料表。如果 Laravel 能夠從遷移名稱判斷資料表名稱,Laravel 將使用指定的資料表預先填寫產生的遷移檔案。否則,您可以簡單地在遷移檔案中手動指定資料表。

如果您想要為產生的遷移指定自訂路徑,您可以在執行 make:migration 命令時使用 --path 選項。給定的路徑應相對於應用程式的基本路徑。

遷移 stub 可以使用stub 發佈來自訂。

壓縮遷移

當您建置應用程式時,您可能會隨著時間的推移累積越來越多的遷移。這可能會導致您的 database/migrations 目錄膨脹,其中可能包含數百個遷移。如果您願意,您可以將您的遷移「壓縮」成單一 SQL 檔案。若要開始,請執行 schema:dump 命令

1php artisan schema:dump
2 
3# Dump the current database schema and prune all existing migrations...
4php artisan schema:dump --prune

當您執行此命令時,Laravel 會將「schema」檔案寫入您應用程式的 database/schema 目錄。schema 檔案的名稱將對應於資料庫連線。現在,當您嘗試遷移資料庫且沒有其他遷移已執行時,Laravel 將首先執行您正在使用的資料庫連線的 schema 檔案中的 SQL 陳述式。在執行 schema 檔案的 SQL 陳述式後,Laravel 將執行任何不屬於 schema 轉儲的剩餘遷移。

如果您的應用程式的測試使用與您在本地開發期間通常使用的資料庫連線不同的資料庫連線,您應確保您已使用該資料庫連線轉儲 schema 檔案,以便您的測試能夠建置您的資料庫。您可能希望在轉儲您在本地開發期間通常使用的資料庫連線後執行此操作

1php artisan schema:dump
2php artisan schema:dump --database=testing --prune

您應將您的資料庫 schema 檔案提交到原始碼控制,以便您的團隊中的其他新開發人員可以快速建立您應用程式的初始資料庫結構。

遷移壓縮僅適用於 MariaDB、MySQL、PostgreSQL 和 SQLite 資料庫,並使用資料庫的命令列用戶端。

遷移結構

遷移類別包含兩個方法:updownup 方法用於將新的資料表、資料行或索引新增到您的資料庫,而 down 方法應反轉 up 方法執行的操作。

在這兩個方法中,您都可以使用 Laravel schema 建構器來表達式地建立和修改資料表。若要了解 Schema 建構器上所有可用的方法,請查看其文件。例如,以下遷移會建立 flights 資料表

1<?php
2 
3use Illuminate\Database\Migrations\Migration;
4use Illuminate\Database\Schema\Blueprint;
5use Illuminate\Support\Facades\Schema;
6 
7return new class extends Migration
8{
9 /**
10 * Run the migrations.
11 */
12 public function up(): void
13 {
14 Schema::create('flights', function (Blueprint $table) {
15 $table->id();
16 $table->string('name');
17 $table->string('airline');
18 $table->timestamps();
19 });
20 }
21 
22 /**
23 * Reverse the migrations.
24 */
25 public function down(): void
26 {
27 Schema::drop('flights');
28 }
29};

設定遷移連線

如果您的遷移將與應用程式預設資料庫連線以外的資料庫連線互動,您應設定遷移的 $connection 屬性

1/**
2 * The database connection that should be used by the migration.
3 *
4 * @var string
5 */
6protected $connection = 'pgsql';
7 
8/**
9 * Run the migrations.
10 */
11public function up(): void
12{
13 // ...
14}

執行遷移

若要執行所有未完成的遷移,請執行 migrate Artisan 命令

1php artisan migrate

如果您想查看到目前為止已執行的遷移,您可以使用 migrate:status Artisan 命令

1php artisan migrate:status

如果您想查看遷移將執行的 SQL 陳述式,而實際上不執行它們,您可以為 migrate 命令提供 --pretend 旗標

1php artisan migrate --pretend

隔離遷移執行

如果您要跨多個伺服器部署應用程式,並將遷移作為部署過程的一部分執行,您可能不希望兩台伺服器同時嘗試遷移資料庫。為了避免這種情況,您可以在調用 migrate 命令時使用 isolated 選項。

當提供 isolated 選項時,Laravel 將在使用應用程式的快取驅動程式取得原子鎖定後,再嘗試執行遷移。當持有該鎖定時,所有其他嘗試執行 migrate 命令的操作都將不會執行;但是,該命令仍將以成功結束狀態碼退出

1php artisan migrate --isolated

若要使用此功能,您的應用程式必須使用 memcachedredisdynamodbdatabasefilearray 快取驅動程式作為應用程式的預設快取驅動程式。此外,所有伺服器都必須與相同的中央快取伺服器通訊。

強制遷移在生產環境中執行

某些遷移操作具有破壞性,這表示它們可能會導致您遺失資料。為了保護您免於對生產資料庫執行這些命令,系統會在執行命令之前提示您確認。若要強制命令在沒有提示的情況下執行,請使用 --force 旗標

1php artisan migrate --force

回滾遷移

若要回滾最新的遷移操作,您可以使用 rollback Artisan 命令。此命令會回滾最後「批次」的遷移,其中可能包含多個遷移檔案

1php artisan migrate:rollback

您可以透過為 rollback 命令提供 step 選項來回滾有限數量的遷移。例如,以下命令將回滾最後五個遷移

1php artisan migrate:rollback --step=5

您可以透過為 rollback 命令提供 batch 選項來回滾特定「批次」的遷移,其中 batch 選項對應於應用程式 migrations 資料庫資料表中的批次值。例如,以下命令將回滾批次三中的所有遷移

1php artisan migrate:rollback --batch=3

如果您想查看遷移將執行的 SQL 陳述式,而實際上不執行它們,您可以為 migrate:rollback 命令提供 --pretend 旗標

1php artisan migrate:rollback --pretend

migrate:reset 命令將回滾您應用程式的所有遷移

1php artisan migrate:reset

使用單一命令回滾和遷移

migrate:refresh 命令將回滾您的所有遷移,然後執行 migrate 命令。此命令有效地重新建立您的整個資料庫

1php artisan migrate:refresh
2 
3# Refresh the database and run all database seeds...
4php artisan migrate:refresh --seed

您可以透過為 refresh 命令提供 step 選項來回滾和重新遷移有限數量的遷移。例如,以下命令將回滾並重新遷移最後五個遷移

1php artisan migrate:refresh --step=5

刪除所有資料表並遷移

migrate:fresh 命令將從資料庫中刪除所有資料表,然後執行 migrate 命令

1php artisan migrate:fresh
2 
3php artisan migrate:fresh --seed

預設情況下,migrate:fresh 命令僅從預設資料庫連線中刪除資料表。但是,您可以使用 --database 選項來指定應遷移的資料庫連線。資料庫連線名稱應對應於應用程式 database 設定檔中定義的連線

1php artisan migrate:fresh --database=admin

無論資料表的前綴為何,migrate:fresh 命令都會刪除所有資料庫資料表。在與其他應用程式共用的資料庫上開發時,應謹慎使用此命令。

資料表

建立資料表

若要建立新的資料庫資料表,請使用 Schema facade 上的 create 方法。create 方法接受兩個引數:第一個是資料表的名稱,而第二個是接收 Blueprint 物件的 closure,可用於定義新的資料表

1use Illuminate\Database\Schema\Blueprint;
2use Illuminate\Support\Facades\Schema;
3 
4Schema::create('users', function (Blueprint $table) {
5 $table->id();
6 $table->string('name');
7 $table->string('email');
8 $table->timestamps();
9});

建立資料表時,您可以使用 schema 建構器的任何資料行方法來定義資料表的資料行。

判斷資料表 / 資料行是否存在

您可以使用 hasTablehasColumnhasIndex 方法來判斷資料表、資料行或索引是否存在

1if (Schema::hasTable('users')) {
2 // The "users" table exists...
3}
4 
5if (Schema::hasColumn('users', 'email')) {
6 // The "users" table exists and has an "email" column...
7}
8 
9if (Schema::hasIndex('users', ['email'], 'unique')) {
10 // The "users" table exists and has a unique index on the "email" column...
11}

資料庫連線和資料表選項

如果您想在不是應用程式預設連線的資料庫連線上執行 schema 操作,請使用 connection 方法

1Schema::connection('sqlite')->create('users', function (Blueprint $table) {
2 $table->id();
3});

此外,還可以使用一些其他屬性和方法來定義資料表建立的其他方面。engine 屬性可用於在使用 MariaDB 或 MySQL 時指定資料表的儲存引擎

1Schema::create('users', function (Blueprint $table) {
2 $table->engine('InnoDB');
3 
4 // ...
5});

charsetcollation 屬性可用於在使用 MariaDB 或 MySQL 時指定已建立資料表的字元集和定序

1Schema::create('users', function (Blueprint $table) {
2 $table->charset('utf8mb4');
3 $table->collation('utf8mb4_unicode_ci');
4 
5 // ...
6});

temporary 方法可用於指示資料表應為「臨時」。臨時資料表僅對目前連線的資料庫 session 可見,並在連線關閉時自動刪除

1Schema::create('calculations', function (Blueprint $table) {
2 $table->temporary();
3 
4 // ...
5});

如果您想將「註解」新增到資料庫資料表,您可以調用資料表實例上的 comment 方法。目前 MariaDB、MySQL 和 PostgreSQL 僅支援資料表註解

1Schema::create('calculations', function (Blueprint $table) {
2 $table->comment('Business calculations');
3 
4 // ...
5});

更新資料表

Schema facade 上的 table 方法可用於更新現有的資料表。與 create 方法類似,table 方法接受兩個引數:資料表的名稱和接收 Blueprint 實例的 closure,您可以使用該實例將資料行或索引新增到資料表

1use Illuminate\Database\Schema\Blueprint;
2use Illuminate\Support\Facades\Schema;
3 
4Schema::table('users', function (Blueprint $table) {
5 $table->integer('votes');
6});

重新命名 / 刪除資料表

若要重新命名現有的資料庫資料表,請使用 rename 方法

1use Illuminate\Support\Facades\Schema;
2 
3Schema::rename($from, $to);

若要刪除現有的資料表,您可以使用 dropdropIfExists 方法

1Schema::drop('users');
2 
3Schema::dropIfExists('users');

重新命名具有外鍵的資料表

在重新命名資料表之前,您應驗證資料表上的任何外鍵約束在您的遷移檔案中是否具有明確的名稱,而不是讓 Laravel 指派基於慣例的名稱。否則,外鍵約束名稱將會參照舊的資料表名稱。

資料行

建立資料行

Schema facade 上的 table 方法可用於更新現有的資料表。與 create 方法類似,table 方法接受兩個引數:資料表的名稱和接收 Illuminate\Database\Schema\Blueprint 實例的 closure,您可以使用該實例將資料行新增到資料表

1use Illuminate\Database\Schema\Blueprint;
2use Illuminate\Support\Facades\Schema;
3 
4Schema::table('users', function (Blueprint $table) {
5 $table->integer('votes');
6});

可用的資料行類型

schema 建構器 blueprint 提供了各種方法,這些方法對應於您可以新增到資料庫資料表的不同資料行類型。下表列出了每個可用的方法

布林值類型

字串 & 文字類型

數值類型

日期 & 時間類型

二進制類型

物件 & Json 類型

UUID & ULID 類型

空間類型

關聯類型

特殊類型

bigIncrements()

bigIncrements 方法會建立自動遞增的 UNSIGNED BIGINT(主鍵)等效資料行

1$table->bigIncrements('id');

bigInteger()

bigInteger 方法會建立 BIGINT 等效資料行

1$table->bigInteger('votes');

binary()

binary 方法會建立 BLOB 等效資料行

1$table->binary('photo');

當使用 MySQL、MariaDB 或 SQL Server 時,您可以傳遞 lengthfixed 引數來建立 VARBINARYBINARY 等效資料行

1$table->binary('data', length: 16); // VARBINARY(16)
2 
3$table->binary('data', length: 16, fixed: true); // BINARY(16)

boolean()

boolean 方法會建立 BOOLEAN 等效資料行

1$table->boolean('confirmed');

char()

char 方法會建立具有給定長度的 CHAR 等效資料行

1$table->char('name', length: 100);

dateTimeTz()

dateTimeTz 方法會建立 DATETIME(帶時區)等效資料行,並具有可選的小數秒精確度

1$table->dateTimeTz('created_at', precision: 0);

dateTime()

dateTime 方法會建立 DATETIME 等效資料行,並具有可選的小數秒精確度

1$table->dateTime('created_at', precision: 0);

date()

date 方法會建立 DATE 等效資料行

1$table->date('created_at');

decimal()

decimal 方法會建立具有給定精確度(總位數)和小數位數(小數位數)的 DECIMAL 等效資料行

1$table->decimal('amount', total: 8, places: 2);

double()

double 方法會建立 DOUBLE 等效資料行

1$table->double('amount');

enum()

enum 方法會建立具有給定有效值的 ENUM 等效資料行

1$table->enum('difficulty', ['easy', 'hard']);

float()

float 方法會建立具有給定精確度的 FLOAT 等效資料行

1$table->float('amount', precision: 53);

foreignId()

foreignId 方法會建立 UNSIGNED BIGINT 等效資料行

1$table->foreignId('user_id');

foreignIdFor()

foreignIdFor 方法會為給定的模型類別新增 {column}_id 等效資料行。資料行類型將為 UNSIGNED BIGINTCHAR(36)CHAR(26),具體取決於模型鍵類型

1$table->foreignIdFor(User::class);

foreignUlid()

foreignUlid 方法會建立 ULID 等效資料行

1$table->foreignUlid('user_id');

foreignUuid()

foreignUuid 方法會建立 UUID 等效資料行

1$table->foreignUuid('user_id');

geography()

geography 方法會建立具有給定空間類型和 SRID(空間參考系統識別碼)的 GEOGRAPHY 等效資料行

1$table->geography('coordinates', subtype: 'point', srid: 4326);

對空間類型的支援取決於您的資料庫驅動程式。請參閱您的資料庫文件。如果您的應用程式正在使用 PostgreSQL 資料庫,您必須先安裝 PostGIS 擴充功能,才能使用 geography 方法。

geometry()

geometry 方法會建立具有給定空間類型和 SRID(空間參考系統識別碼)的 GEOMETRY 等效資料行

1$table->geometry('positions', subtype: 'point', srid: 0);

對空間類型的支援取決於您的資料庫驅動程式。請參閱您的資料庫文件。如果您的應用程式正在使用 PostgreSQL 資料庫,您必須先安裝 PostGIS 擴充功能,才能使用 geometry 方法。

id()

id 方法是 bigIncrements 方法的別名。預設情況下,此方法將建立 id 資料行;但是,如果您想為資料行指派不同的名稱,可以傳遞資料行名稱

1$table->id();

increments()

increments 方法會建立自動遞增的 UNSIGNED INTEGER 等效資料行作為主鍵

1$table->increments('id');

integer()

integer 方法會建立 INTEGER 等效資料行

1$table->integer('votes');

ipAddress()

ipAddress 方法會建立 VARCHAR 等效資料行

1$table->ipAddress('visitor');

當使用 PostgreSQL 時,將會建立 INET 資料行。

json()

json 方法會建立 JSON 等效資料行

1$table->json('options');

當使用 SQLite 時,將會建立 TEXT 資料行。

jsonb()

jsonb 方法會建立 JSONB 等效資料行

1$table->jsonb('options');

當使用 SQLite 時,將會建立 TEXT 資料行。

longText()

longText 方法會建立 LONGTEXT 等效資料行

1$table->longText('description');

當使用 MySQL 或 MariaDB 時,您可以將 binary 字元集應用於資料行,以建立 LONGBLOB 等效資料行

1$table->longText('data')->charset('binary'); // LONGBLOB

macAddress()

macAddress 方法會建立一個旨在保存 MAC 位址的資料行。某些資料庫系統(例如 PostgreSQL)具有用於此類型資料的專用資料行類型。其他資料庫系統將使用字串等效資料行

1$table->macAddress('device');

mediumIncrements()

mediumIncrements 方法會建立自動遞增的 UNSIGNED MEDIUMINT 等效資料行作為主鍵

1$table->mediumIncrements('id');

mediumInteger()

mediumInteger 方法會建立 MEDIUMINT 等效資料行

1$table->mediumInteger('votes');

mediumText()

mediumText 方法會建立 MEDIUMTEXT 等效資料行

1$table->mediumText('description');

當使用 MySQL 或 MariaDB 時,您可以將 binary 字元集應用於資料行,以建立 MEDIUMBLOB 等效資料行

1$table->mediumText('data')->charset('binary'); // MEDIUMBLOB

morphs()

morphs 方法是一種便利方法,可新增 {column}_id 等效資料行和 {column}_type VARCHAR 等效資料行。{column}_id 的資料行類型將為 UNSIGNED BIGINTCHAR(36)CHAR(26),具體取決於模型鍵類型。

此方法旨在用於定義多態Eloquent 關聯所需的資料行。在以下範例中,將建立 taggable_idtaggable_type 資料行

1$table->morphs('taggable');

nullableMorphs()

此方法與 morphs 方法類似;但是,建立的資料行將為「可為空值」

1$table->nullableMorphs('taggable');

nullableUlidMorphs()

此方法與 ulidMorphs 方法類似;但是,建立的資料行將為「可為空值」

1$table->nullableUlidMorphs('taggable');

nullableUuidMorphs()

此方法與 uuidMorphs 方法類似;但是,建立的資料行將為「可為空值」

1$table->nullableUuidMorphs('taggable');

rememberToken()

rememberToken 方法會建立可為空值的 VARCHAR(100) 等效資料行,該資料行旨在儲存目前的「記住我」身份驗證權杖

1$table->rememberToken();

set()

set 方法會建立具有給定有效值清單的 SET 等效資料行

1$table->set('flavors', ['strawberry', 'vanilla']);

smallIncrements()

smallIncrements 方法會建立自動遞增的 UNSIGNED SMALLINT 等效資料行作為主鍵

1$table->smallIncrements('id');

smallInteger()

smallInteger 方法會建立 SMALLINT 等效資料行

1$table->smallInteger('votes');

softDeletesTz()

softDeletesTz 方法會新增可為空值的 deleted_at TIMESTAMP(帶時區)等效資料行,並具有可選的小數秒精確度。此資料行旨在儲存 Eloquent「軟刪除」功能所需的 deleted_at 時間戳記

1$table->softDeletesTz('deleted_at', precision: 0);

softDeletes()

softDeletes 方法會新增可為空值的 deleted_at TIMESTAMP 等效資料行,並具有可選的小數秒精確度。此資料行旨在儲存 Eloquent「軟刪除」功能所需的 deleted_at 時間戳記

1$table->softDeletes('deleted_at', precision: 0);

string()

string 方法會建立具有給定長度的 VARCHAR 等效資料行

1$table->string('name', length: 100);

text()

text 方法會建立 TEXT 等效資料行

1$table->text('description');

當使用 MySQL 或 MariaDB 時,您可以將 binary 字元集應用於資料行,以建立 BLOB 等效資料行

1$table->text('data')->charset('binary'); // BLOB

timeTz()

timeTz 方法會建立 TIME(帶時區)等效資料行,並具有可選的小數秒精確度

1$table->timeTz('sunrise', precision: 0);

time()

time 方法會建立 TIME 等效資料行,並具有可選的小數秒精確度

1$table->time('sunrise', precision: 0);

timestampTz()

timestampTz 方法會建立 TIMESTAMP(帶時區)等效資料行,並具有可選的小數秒精確度

1$table->timestampTz('added_at', precision: 0);

timestamp()

timestamp 方法會建立 TIMESTAMP 等效資料行,並具有可選的小數秒精確度

1$table->timestamp('added_at', precision: 0);

timestampsTz()

timestampsTz 方法會建立 created_atupdated_at TIMESTAMP(帶時區)等效資料行,並具有可選的小數秒精確度

1$table->timestampsTz(precision: 0);

timestamps()

timestamps 方法會建立 created_atupdated_at TIMESTAMP 等效資料行,並具有可選的小數秒精確度

1$table->timestamps(precision: 0);

tinyIncrements()

tinyIncrements 方法會建立自動遞增的 UNSIGNED TINYINT 等效資料行作為主鍵

1$table->tinyIncrements('id');

tinyInteger()

tinyInteger 方法會建立 TINYINT 等效資料行

1$table->tinyInteger('votes');

tinyText()

tinyText 方法會建立一個 TINYTEXT 相等的欄位

1$table->tinyText('notes');

當使用 MySQL 或 MariaDB 時,您可以將 binary 字元集應用於欄位,以建立一個 TINYBLOB 相等的欄位

1$table->tinyText('data')->charset('binary'); // TINYBLOB

unsignedBigInteger()

unsignedBigInteger 方法會建立一個 UNSIGNED BIGINT 相等的欄位

1$table->unsignedBigInteger('votes');

unsignedInteger()

unsignedInteger 方法會建立一個 UNSIGNED INTEGER 相等的欄位

1$table->unsignedInteger('votes');

unsignedMediumInteger()

unsignedMediumInteger 方法會建立一個 UNSIGNED MEDIUMINT 相等的欄位

1$table->unsignedMediumInteger('votes');

unsignedSmallInteger()

unsignedSmallInteger 方法會建立一個 UNSIGNED SMALLINT 相等的欄位

1$table->unsignedSmallInteger('votes');

unsignedTinyInteger()

unsignedTinyInteger 方法會建立一個 UNSIGNED TINYINT 相等的欄位

1$table->unsignedTinyInteger('votes');

ulidMorphs()

ulidMorphs 方法是一個方便的方法,它會新增一個 {column}_id CHAR(26) 相等的欄位和一個 {column}_type VARCHAR 相等的欄位。

此方法旨在用於定義多型 Eloquent 關聯 所需的欄位,該關聯使用 ULID 識別符。在以下範例中,將會建立 taggable_idtaggable_type 欄位

1$table->ulidMorphs('taggable');

uuidMorphs()

uuidMorphs 方法是一個方便的方法,它會新增一個 {column}_id CHAR(36) 相等的欄位和一個 {column}_type VARCHAR 相等的欄位。

此方法旨在用於定義多型 Eloquent 關聯 所需的欄位,該關聯使用 UUID 識別符。在以下範例中,將會建立 taggable_idtaggable_type 欄位

1$table->uuidMorphs('taggable');

ulid()

ulid 方法會建立一個 ULID 相等的欄位

1$table->ulid('id');

uuid()

uuid 方法會建立一個 UUID 相等的欄位

1$table->uuid('id');

vector()

vector 方法會建立一個 vector 相等的欄位

1$table->vector('embedding', dimensions: 100);

year()

year 方法會建立一個 YEAR 相等的欄位

1$table->year('birth_year');

資料行修飾符

除了上面列出的欄位類型外,還有幾種欄位「修飾詞」可以在將欄位新增到資料庫表格時使用。例如,要使欄位「可為空」,您可以使用 nullable 方法

1use Illuminate\Database\Schema\Blueprint;
2use Illuminate\Support\Facades\Schema;
3 
4Schema::table('users', function (Blueprint $table) {
5 $table->string('email')->nullable();
6});

下表包含所有可用的欄位修飾詞。此列表不包含 索引修飾詞

修飾詞 描述
->after('column') 將欄位放置在另一個欄位「之後」(MariaDB / MySQL)。
->autoIncrement() INTEGER 欄位設定為自動遞增 (主鍵)。
->charset('utf8mb4') 為欄位指定字元集 (MariaDB / MySQL)。
->collation('utf8mb4_unicode_ci') 為欄位指定排序規則。
->comment('my comment') 為欄位新增註解 (MariaDB / MySQL / PostgreSQL)。
->default($value) 為欄位指定「預設」值。
->first() 將欄位放置在表格中的「最前面」(MariaDB / MySQL)。
->from($integer) 設定自動遞增欄位的起始值 (MariaDB / MySQL / PostgreSQL)。
->invisible() 使欄位在 SELECT * 查詢中「不可見」(MariaDB / MySQL)。
->nullable($value = true) 允許將 NULL 值插入欄位中。
->storedAs($expression) 建立儲存的產生欄位 (MariaDB / MySQL / PostgreSQL / SQLite)。
->unsigned() INTEGER 欄位設定為 UNSIGNED (MariaDB / MySQL)。
->useCurrent() TIMESTAMP 欄位設定為使用 CURRENT_TIMESTAMP 作為預設值。
->useCurrentOnUpdate() TIMESTAMP 欄位設定為在記錄更新時使用 CURRENT_TIMESTAMP (MariaDB / MySQL)。
->virtualAs($expression) 建立虛擬產生的欄位 (MariaDB / MySQL / SQLite)。
->generatedAs($expression) 使用指定的序列選項建立身分欄位 (PostgreSQL)。
->always() 定義身分欄位的序列值優先於輸入 (PostgreSQL)。

預設表達式

default 修飾詞接受值或 Illuminate\Database\Query\Expression 實例。使用 Expression 實例將防止 Laravel 將值包在引號中,並允許您使用資料庫特定的函數。當您需要為 JSON 欄位指定預設值時,這種情況特別有用

1<?php
2 
3use Illuminate\Support\Facades\Schema;
4use Illuminate\Database\Schema\Blueprint;
5use Illuminate\Database\Query\Expression;
6use Illuminate\Database\Migrations\Migration;
7 
8return new class extends Migration
9{
10 /**
11 * Run the migrations.
12 */
13 public function up(): void
14 {
15 Schema::create('flights', function (Blueprint $table) {
16 $table->id();
17 $table->json('movies')->default(new Expression('(JSON_ARRAY())'));
18 $table->timestamps();
19 });
20 }
21};

對預設表達式的支援取決於您的資料庫驅動程式、資料庫版本和欄位類型。請參閱您的資料庫文件。

欄位順序

當使用 MariaDB 或 MySQL 資料庫時,可以使用 after 方法在綱要中現有欄位之後新增欄位

1$table->after('password', function (Blueprint $table) {
2 $table->string('address_line1');
3 $table->string('address_line2');
4 $table->string('city');
5});

修改資料行

change 方法允許您修改現有欄位的類型和屬性。例如,您可能希望增加 string 欄位的大小。為了查看 change 方法的實際效果,讓我們將 name 欄位的大小從 25 增加到 50。為了實現這一點,我們只需定義欄位的新狀態,然後呼叫 change 方法

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

修改欄位時,您必須明確包含您想要保留在欄位定義中的所有修飾詞 - 任何遺失的屬性都將被刪除。例如,要保留 unsigneddefaultcomment 屬性,您必須在變更欄位時明確呼叫每個修飾詞

1Schema::table('users', function (Blueprint $table) {
2 $table->integer('votes')->unsigned()->default(1)->comment('my comment')->change();
3});

change 方法不會變更欄位的索引。因此,您可以使用索引修飾詞在修改欄位時明確新增或刪除索引

1// Add an index...
2$table->bigIncrements('id')->primary()->change();
3 
4// Drop an index...
5$table->char('postal_code', 10)->unique(false)->change();

重新命名資料行

要重新命名欄位,您可以使用綱要建立器提供的 renameColumn 方法

1Schema::table('users', function (Blueprint $table) {
2 $table->renameColumn('from', 'to');
3});

刪除資料行

要刪除欄位,您可以使用綱要建立器上的 dropColumn 方法

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

您可以將欄位名稱陣列傳遞給 dropColumn 方法,從表格中刪除多個欄位

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

可用的命令別名

Laravel 提供了幾個與刪除常見欄位類型相關的便利方法。下表描述了這些方法中的每一個

命令 描述
$table->dropMorphs('morphable'); 刪除 morphable_idmorphable_type 欄位。
$table->dropRememberToken(); 刪除 remember_token 欄位。
$table->dropSoftDeletes(); 刪除 deleted_at 欄位。
$table->dropSoftDeletesTz(); dropSoftDeletes() 方法的別名。
$table->dropTimestamps(); 刪除 created_atupdated_at 欄位。
$table->dropTimestampsTz(); dropTimestamps() 方法的別名。

索引

建立索引

Laravel 綱要建立器支援多種類型的索引。以下範例建立一個新的 email 欄位,並指定其值應為唯一值。要建立索引,我們可以將 unique 方法鏈接到欄位定義

1use Illuminate\Database\Schema\Blueprint;
2use Illuminate\Support\Facades\Schema;
3 
4Schema::table('users', function (Blueprint $table) {
5 $table->string('email')->unique();
6});

或者,您可以在定義欄位後建立索引。為此,您應該在綱要建立器藍圖上呼叫 unique 方法。此方法接受應接收唯一索引的欄位名稱

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

您甚至可以將欄位陣列傳遞給索引方法,以建立複合 (或組合) 索引

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

建立索引時,Laravel 將根據表格、欄位名稱和索引類型自動產生索引名稱,但您可以將第二個引數傳遞給方法來自行指定索引名稱

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

可用的索引類型

Laravel 的綱要建立器藍圖類別提供了用於建立 Laravel 支援的每種索引類型的方法。每個索引方法都接受一個可選的第二個引數,以指定索引的名稱。如果省略,名稱將從用於索引的表格和欄位名稱以及索引類型衍生而來。下表描述了每個可用的索引方法

命令 描述
$table->primary('id'); 新增主鍵。
$table->primary(['id', 'parent_id']); 新增複合鍵。
$table->unique('email'); 新增唯一索引。
$table->index('state'); 新增索引。
$table->fullText('body'); 新增全文索引 (MariaDB / MySQL / PostgreSQL)。
$table->fullText('body')->language('english'); 新增指定語言的全文索引 (PostgreSQL)。
$table->spatialIndex('location'); 新增空間索引 (SQLite 除外)。

重新命名索引

要重新命名索引,您可以使用綱要建立器藍圖提供的 renameIndex 方法。此方法接受當前索引名稱作為其第一個引數,並接受所需的名稱作為其第二個引數

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

刪除索引

要刪除索引,您必須指定索引的名稱。預設情況下,Laravel 會根據表格名稱、索引欄位的名稱和索引類型自動指派索引名稱。以下是一些範例

命令 描述
$table->dropPrimary('users_id_primary'); 從 "users" 表格中刪除主鍵。
$table->dropUnique('users_email_unique'); 從 "users" 表格中刪除唯一索引。
$table->dropIndex('geo_state_index'); 從 "geo" 表格中刪除基本索引。
$table->dropFullText('posts_body_fulltext'); 從 "posts" 表格中刪除全文索引。
$table->dropSpatialIndex('geo_location_spatialindex'); 從 "geo" 表格中刪除空間索引 (SQLite 除外)。

如果您將欄位陣列傳遞到刪除索引的方法中,則會根據表格名稱、欄位和索引類型產生慣用的索引名稱

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

外鍵約束

Laravel 還支援建立外鍵約束,該約束用於在資料庫層級強制參考完整性。例如,讓我們在 posts 表格上定義一個 user_id 欄位,該欄位參考 users 表格上的 id 欄位

1use Illuminate\Database\Schema\Blueprint;
2use Illuminate\Support\Facades\Schema;
3 
4Schema::table('posts', function (Blueprint $table) {
5 $table->unsignedBigInteger('user_id');
6 
7 $table->foreign('user_id')->references('id')->on('users');
8});

由於此語法相當冗長,Laravel 提供了額外的、更簡潔的方法,這些方法使用慣例來提供更好的開發人員體驗。當使用 foreignId 方法建立欄位時,上面的範例可以改寫如下

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

foreignId 方法會建立一個 UNSIGNED BIGINT 相等的欄位,而 constrained 方法將使用慣例來確定要參考的表格和欄位。如果您的表格名稱與 Laravel 的慣例不符,您可以手動將其提供給 constrained 方法。此外,也可以指定應指派給產生的索引的名稱

1Schema::table('posts', function (Blueprint $table) {
2 $table->foreignId('user_id')->constrained(
3 table: 'users', indexName: 'posts_user_id'
4 );
5});

您也可以為約束的 "on delete" 和 "on update" 屬性指定所需的動作

1$table->foreignId('user_id')
2 ->constrained()
3 ->onUpdate('cascade')
4 ->onDelete('cascade');

也為這些動作提供了另一種表達性語法

方法 描述
$table->cascadeOnUpdate(); 更新應串聯。
$table->restrictOnUpdate(); 更新應受到限制。
$table->nullOnUpdate(); 更新應將外鍵值設定為 null。
$table->noActionOnUpdate(); 更新時不執行任何動作。
$table->cascadeOnDelete(); 刪除應串聯。
$table->restrictOnDelete(); 刪除應受到限制。
$table->nullOnDelete(); 刪除應將外鍵值設定為 null。
$table->noActionOnDelete(); 如果存在子記錄,則阻止刪除。

任何其他 欄位修飾詞 都必須在 constrained 方法之前呼叫

1$table->foreignId('user_id')
2 ->nullable()
3 ->constrained();

刪除外鍵

要刪除外鍵,您可以使用 dropForeign 方法,並將要刪除的外鍵約束的名稱作為引數傳遞。外鍵約束使用與索引相同的命名慣例。換句話說,外鍵約束名稱基於表格名稱和約束中的欄位,後跟 "_foreign" 後綴

1$table->dropForeign('posts_user_id_foreign');

或者,您可以將包含持有外鍵的欄位名稱的陣列傳遞給 dropForeign 方法。陣列將使用 Laravel 的約束命名慣例轉換為外鍵約束名稱

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

切換外鍵約束

您可以使用以下方法在遷移中啟用或停用外鍵約束

1Schema::enableForeignKeyConstraints();
2 
3Schema::disableForeignKeyConstraints();
4 
5Schema::withoutForeignKeyConstraints(function () {
6 // Constraints disabled within this closure...
7});

SQLite 預設停用外鍵約束。當使用 SQLite 時,請確保在您的資料庫設定中啟用外鍵支援,然後再嘗試在遷移中建立它們。

事件

為了方便起見,每個遷移操作都會分派一個 事件。以下所有事件都擴展了基礎 Illuminate\Database\Events\MigrationEvent 類別

類別 描述
Illuminate\Database\Events\MigrationsStarted 即將執行一批遷移。
Illuminate\Database\Events\MigrationsEnded 一批遷移已完成執行。
Illuminate\Database\Events\MigrationStarted 即將執行單個遷移。
Illuminate\Database\Events\MigrationEnded 單個遷移已完成執行。
Illuminate\Database\Events\NoPendingMigrations 遷移命令未找到待處理的遷移。
Illuminate\Database\Events\SchemaDumped 資料庫綱要轉儲已完成。
Illuminate\Database\Events\SchemaLoaded 現有的資料庫綱要轉儲已載入。

Laravel 是最有效率的方式來
建構、部署和監控軟體。