資料庫:遷移
簡介
遷移就像您資料庫的版本控制,允許您的團隊定義和分享應用程式的資料庫架構定義。如果您曾經在從原始碼控制拉取您的變更後,必須告訴隊友手動將欄位新增到他們的本機資料庫架構,那麼您就面臨了資料庫遷移所要解決的問題。
Laravel 的 Schema
facade 提供對跨 Laravel 所有支援的資料庫系統建立和操作資料表的資料庫不可知支援。通常,遷移會使用此 facade 來建立和修改資料庫資料表和欄位。
產生遷移
您可以使用 make:migration
Artisan 命令 來產生資料庫遷移。新的遷移將放置在您的 database/migrations
目錄中。每個遷移檔案名稱都包含一個時間戳記,讓 Laravel 可以判斷遷移的順序。
php artisan make:migration create_flights_table
Laravel 將使用遷移的名稱來嘗試猜測資料表的名稱,以及遷移是否將建立新的資料表。如果 Laravel 能夠從遷移名稱判斷資料表名稱,Laravel 將使用指定的資料表預先填入產生的遷移檔案。否則,您只需在遷移檔案中手動指定資料表即可。
如果您想要為產生的遷移指定自訂路徑,您可以在執行 make:migration
命令時使用 --path
選項。給定的路徑應該相對於您的應用程式基本路徑。
可以使用 stub 發佈 來客製化遷移 stub。
壓縮遷移
當您建構應用程式時,隨著時間的推移,您可能會累積越來越多的遷移。這可能會導致您的 database/migrations
目錄膨脹,其中可能包含數百個遷移。如果您願意,您可以將您的遷移「壓縮」成一個 SQL 檔案。要開始,請執行 schema:dump
命令
php artisan schema:dump # Dump the current database schema and prune all existing migrations...php artisan schema:dump --prune
當您執行此命令時,Laravel 會將「架構」檔案寫入您應用程式的 database/schema
目錄中。架構檔案的名稱將對應於資料庫連線。現在,當您嘗試遷移您的資料庫且沒有執行其他遷移時,Laravel 將首先執行您正在使用的資料庫連線的架構檔案中的 SQL 陳述式。在執行架構檔案的 SQL 陳述式之後,Laravel 將執行任何未包含在架構傾印中的剩餘遷移。
如果您的應用程式的測試使用與您在本地開發期間通常使用的不同的資料庫連線,您應確保您已使用該資料庫連線傾印架構檔案,以便您的測試能夠建構您的資料庫。您可能希望在傾印您在本地開發期間通常使用的資料庫連線後執行此操作
php artisan schema:dumpphp artisan schema:dump --database=testing --prune
您應該將您的資料庫架構檔案提交到原始碼控制,以便您的團隊中其他新的開發人員可以快速建立您應用程式的初始資料庫結構。
遷移壓縮僅適用於 MariaDB、MySQL、PostgreSQL 和 SQLite 資料庫,並使用資料庫的命令列用戶端。
遷移結構
遷移類別包含兩個方法:up
和 down
。up
方法用於在您的資料庫中新增新的資料表、欄位或索引,而 down
方法應該反轉 up
方法執行的操作。
在這兩個方法中,您都可以使用 Laravel 架構建構器來具體地建立和修改資料表。要了解 Schema
建構器上所有可用的方法,請查看其文件。例如,以下遷移會建立 flights
資料表
<?php use Illuminate\Database\Migrations\Migration;use Illuminate\Database\Schema\Blueprint;use Illuminate\Support\Facades\Schema; return new class extends Migration{ /** * Run the migrations. */ public function up(): void { Schema::create('flights', function (Blueprint $table) { $table->id(); $table->string('name'); $table->string('airline'); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::drop('flights'); }};
設定遷移連線
如果您的遷移將與您的應用程式預設資料庫連線以外的資料庫連線互動,您應該設定遷移的 $connection
屬性
/** * The database connection that should be used by the migration. * * @var string */protected $connection = 'pgsql'; /** * Run the migrations. */public function up(): void{ // ...}
執行遷移
要執行所有您未執行的遷移,請執行 migrate
Artisan 命令
php artisan migrate
如果您想要查看目前為止已執行的遷移,您可以使用 migrate:status
Artisan 命令
php artisan migrate:status
如果您想要查看遷移將執行的 SQL 陳述式,而實際上不執行它們,您可以向 migrate
命令提供 --pretend
旗標
php artisan migrate --pretend
隔離遷移執行
如果您正在跨多個伺服器部署您的應用程式,並將執行遷移作為您部署過程的一部分,您可能不希望兩個伺服器同時嘗試遷移資料庫。為了避免這種情況,您可以在調用 migrate
命令時使用 isolated
選項。
當提供 isolated
選項時,Laravel 將在使用您應用程式的快取驅動程式嘗試執行遷移之前取得原子鎖定。所有其他在持有該鎖定時嘗試執行 migrate
命令的嘗試將不會執行;但是,該命令仍將以成功的退出狀態碼退出
php artisan migrate --isolated
要使用此功能,您的應用程式必須使用 memcached
、redis
、dynamodb
、database
、file
或 array
快取驅動程式作為您應用程式的預設快取驅動程式。此外,所有伺服器都必須與同一個中央快取伺服器通訊。
強制在生產環境中執行遷移
有些遷移操作具有破壞性,這表示它們可能會導致您遺失資料。為了保護您不會在正式環境資料庫上執行這些指令,在執行指令之前,系統會提示您確認。若要強制執行這些指令而不顯示提示,請使用 --force
旗標。
php artisan migrate --force
回滾遷移
若要回滾最新的遷移操作,您可以使用 rollback
Artisan 指令。此指令會回滾最後一個「批次」的遷移,其中可能包含多個遷移檔案。
php artisan migrate:rollback
您可以透過在 rollback
指令中提供 step
選項來回滾有限數量的遷移。例如,以下指令將回滾最後五個遷移。
php artisan migrate:rollback --step=5
您可以透過在 rollback
指令中提供 batch
選項來回滾特定「批次」的遷移,其中 batch
選項對應於應用程式 migrations
資料庫表格中的批次值。例如,以下指令將回滾批次三中的所有遷移。
php artisan migrate:rollback --batch=3
如果您想查看遷移將執行的 SQL 語句,但不實際執行它們,您可以在 migrate:rollback
指令中提供 --pretend
旗標。
php artisan migrate:rollback --pretend
migrate:reset
指令將回滾您應用程式的所有遷移。
php artisan migrate:reset
使用單一指令回滾和遷移
migrate:refresh
指令將回滾您的所有遷移,然後執行 migrate
指令。此指令實際上會重新建立您的整個資料庫。
php artisan migrate:refresh # Refresh the database and run all database seeds...php artisan migrate:refresh --seed
您可以透過在 refresh
指令中提供 step
選項來回滾和重新遷移有限數量的遷移。例如,以下指令將回滾並重新遷移最後五個遷移。
php artisan migrate:refresh --step=5
刪除所有表格並遷移
migrate:fresh
指令將刪除資料庫中的所有表格,然後執行 migrate
指令。
php artisan migrate:fresh php artisan migrate:fresh --seed
預設情況下,migrate:fresh
指令只會刪除預設資料庫連線中的表格。但是,您可以使用 --database
選項來指定應該遷移的資料庫連線。資料庫連線名稱應與應用程式 database
設定檔 中定義的連線相對應。
php artisan migrate:fresh --database=admin
migrate:fresh
指令將刪除所有資料庫表格,無論它們的前綴為何。在與其他應用程式共用的資料庫上開發時,應謹慎使用此指令。
資料表
建立資料表
若要建立新的資料庫表格,請在 Schema
facade 上使用 create
方法。create
方法接受兩個引數:第一個是表格的名稱,而第二個是接收 Blueprint
物件的閉包,該物件可用於定義新的表格。
use Illuminate\Database\Schema\Blueprint;use Illuminate\Support\Facades\Schema; Schema::create('users', function (Blueprint $table) { $table->id(); $table->string('name'); $table->string('email'); $table->timestamps();});
建立表格時,您可以使用任何 schema builder 的欄位方法來定義表格的欄位。
判斷表格/欄位的存在
您可以使用 hasTable
、hasColumn
和 hasIndex
方法來判斷表格、欄位或索引是否存在。
if (Schema::hasTable('users')) { // The "users" table exists...} if (Schema::hasColumn('users', 'email')) { // The "users" table exists and has an "email" column...} if (Schema::hasIndex('users', ['email'], 'unique')) { // The "users" table exists and has a unique index on the "email" column...}
資料庫連線和表格選項
如果您想在不是應用程式預設連線的資料庫連線上執行 schema 操作,請使用 connection
方法。
Schema::connection('sqlite')->create('users', function (Blueprint $table) { $table->id();});
此外,還可以使用其他一些屬性和方法來定義表格建立的其他方面。當使用 MariaDB 或 MySQL 時,可以使用 engine
屬性來指定表格的儲存引擎。
Schema::create('users', function (Blueprint $table) { $table->engine('InnoDB'); // ...});
當使用 MariaDB 或 MySQL 時,可以使用 charset
和 collation
屬性來指定所建立表格的字元集和排序規則。
Schema::create('users', function (Blueprint $table) { $table->charset('utf8mb4'); $table->collation('utf8mb4_unicode_ci'); // ...});
temporary
方法可用於指示表格應為「暫時性」。暫時性表格僅對目前連線的資料庫會話可見,並且在連線關閉時會自動刪除。
Schema::create('calculations', function (Blueprint $table) { $table->temporary(); // ...});
如果您想在資料庫表格中加入「註解」,您可以在表格實例上呼叫 comment
方法。目前僅 MariaDB、MySQL 和 PostgreSQL 支援表格註解。
Schema::create('calculations', function (Blueprint $table) { $table->comment('Business calculations'); // ...});
更新資料表
Schema
facade 上的 table
方法可用於更新現有的表格。與 create
方法一樣,table
方法接受兩個引數:表格的名稱和接收 Blueprint
實例的閉包,您可以使用該實例來向表格添加欄位或索引。
use Illuminate\Database\Schema\Blueprint;use Illuminate\Support\Facades\Schema; Schema::table('users', function (Blueprint $table) { $table->integer('votes');});
重新命名 / 刪除資料表
若要重新命名現有的資料庫表格,請使用 rename
方法。
use Illuminate\Support\Facades\Schema; Schema::rename($from, $to);
若要刪除現有的表格,您可以使用 drop
或 dropIfExists
方法。
Schema::drop('users'); Schema::dropIfExists('users');
使用外鍵重新命名表格
在重新命名表格之前,您應驗證表格上的任何外鍵約束在您的遷移檔案中都有明確的名稱,而不是讓 Laravel 指定基於約定的名稱。否則,外鍵約束名稱將參考舊的表格名稱。
欄位
建立欄位
Schema
facade 上的 table
方法可用於更新現有的表格。與 create
方法一樣,table
方法接受兩個引數:表格的名稱和接收 Illuminate\Database\Schema\Blueprint
實例的閉包,您可以使用該實例來向表格添加欄位。
use Illuminate\Database\Schema\Blueprint;use Illuminate\Support\Facades\Schema; Schema::table('users', function (Blueprint $table) { $table->integer('votes');});
可用的欄位類型
schema builder blueprint 提供了各種方法,這些方法對應於您可以添加到資料庫表格的不同類型欄位。下表列出了每個可用的方法。
bigIncrements bigInteger binary boolean char dateTimeTz dateTime date decimal double enum float foreignId foreignIdFor foreignUlid foreignUuid geography geometry id increments integer ipAddress json jsonb longText macAddress mediumIncrements mediumInteger mediumText morphs nullableMorphs nullableTimestamps nullableUlidMorphs nullableUuidMorphs rememberToken set smallIncrements smallInteger softDeletesTz softDeletes string text timeTz time timestampTz timestamp timestampsTz timestamps tinyIncrements tinyInteger tinyText unsignedBigInteger unsignedInteger unsignedMediumInteger unsignedSmallInteger unsignedTinyInteger ulidMorphs uuidMorphs ulid uuid vector year
bigIncrements()
bigIncrements
方法會建立一個等同於自動遞增的 UNSIGNED BIGINT
(主鍵)欄位。
$table->bigIncrements('id');
bigInteger()
bigInteger
方法會建立一個等同於 BIGINT
的欄位。
$table->bigInteger('votes');
binary()
binary
方法會建立一個等同於 BLOB
的欄位。
$table->binary('photo');
當使用 MySQL、MariaDB 或 SQL Server 時,您可以傳遞 length
和 fixed
引數來建立等同於 VARBINARY
或 BINARY
的欄位。
$table->binary('data', length: 16); // VARBINARY(16) $table->binary('data', length: 16, fixed: true); // BINARY(16)
boolean()
boolean
方法會建立一個等同於 BOOLEAN
的欄位。
$table->boolean('confirmed');
char()
char
方法會建立一個指定長度的等同於 CHAR
的欄位。
$table->char('name', length: 100);
dateTimeTz()
dateTimeTz
方法會建立一個等同於 DATETIME
(帶時區) 的欄位,並具有可選的小數秒精度。
$table->dateTimeTz('created_at', precision: 0);
dateTime()
dateTime
方法會建立一個等同於 DATETIME
的欄位,並具有可選的小數秒精度。
$table->dateTime('created_at', precision: 0);
date()
date
方法會建立一個等同於 DATE
的欄位。
$table->date('created_at');
decimal()
decimal
方法會建立一個具有指定精度(總位數)和小數位數(小數點後的位數)的等同於 DECIMAL
的欄位。
$table->decimal('amount', total: 8, places: 2);
double()
double
方法會建立一個等同於 DOUBLE
的欄位。
$table->double('amount');
enum()
enum
方法會建立一個具有指定有效值的等同於 ENUM
的欄位。
$table->enum('difficulty', ['easy', 'hard']);
float()
float
方法會建立一個具有指定精度的等同於 FLOAT
的欄位。
$table->float('amount', precision: 53);
foreignId()
foreignId
方法會建立一個等同於 UNSIGNED BIGINT
的欄位。
$table->foreignId('user_id');
foreignIdFor()
foreignIdFor
方法會為給定的模型類別新增一個等同於 {column}_id
的欄位。欄位類型將會是 UNSIGNED BIGINT
、CHAR(36)
或 CHAR(26)
,取決於模型鍵類型。
$table->foreignIdFor(User::class);
foreignUlid()
foreignUlid
方法會建立一個等同於 ULID
的欄位。
$table->foreignUlid('user_id');
foreignUuid()
foreignUuid
方法會建立一個等同於 UUID
的欄位。
$table->foreignUuid('user_id');
geography()
geography
方法會建立一個具有指定空間類型和 SRID (空間參考系統識別碼) 的等同於 GEOGRAPHY
的欄位。
$table->geography('coordinates', subtype: 'point', srid: 4326);
對空間類型的支援取決於您的資料庫驅動程式。請參閱資料庫的文件。如果您的應用程式正在使用 PostgreSQL 資料庫,您必須安裝 PostGIS 擴充功能,才能使用 geography
方法。
geometry()
geometry
方法會建立一個具有指定空間類型和 SRID (空間參考系統識別碼) 的等同於 GEOMETRY
的欄位。
$table->geometry('positions', subtype: 'point', srid: 0);
對空間類型的支援取決於您的資料庫驅動程式。請參閱資料庫的文件。如果您的應用程式正在使用 PostgreSQL 資料庫,您必須安裝 PostGIS 擴充功能,才能使用 geometry
方法。
id()
id
方法是 bigIncrements
方法的別名。預設情況下,該方法會建立一個 id
欄位;但是,如果您想為欄位指定不同的名稱,則可以傳遞欄位名稱。
$table->id();
increments()
increments
方法會建立一個自動遞增的等同於 UNSIGNED INTEGER
的欄位作為主鍵。
$table->increments('id');
integer()
integer
方法會建立一個等同於 INTEGER
的欄位。
$table->integer('votes');
ipAddress()
ipAddress
方法會建立一個等同於 VARCHAR
的欄位。
$table->ipAddress('visitor');
當使用 PostgreSQL 時,將會建立一個 INET
欄位。
json()
json
方法會建立一個等同於 JSON
的欄位。
$table->json('options');
jsonb()
jsonb
方法會建立一個等同於 JSONB
的欄位。
$table->jsonb('options');
longText()
longText
方法會建立一個等同於 LONGTEXT
的欄位。
$table->longText('description');
當使用 MySQL 或 MariaDB 時,您可以將 binary
字元集套用到該欄位,以便建立等同於 LONGBLOB
的欄位。
$table->longText('data')->charset('binary'); // LONGBLOB
macAddress()
macAddress
方法會建立一個旨在保留 MAC 位址的欄位。某些資料庫系統 (例如 PostgreSQL) 具有專用於此類型資料的欄位類型。其他資料庫系統將使用等同於字串的欄位。
$table->macAddress('device');
mediumIncrements()
mediumIncrements
方法會建立一個自動遞增的等同於 UNSIGNED MEDIUMINT
的欄位作為主鍵。
$table->mediumIncrements('id');
mediumInteger()
mediumInteger
方法會建立一個等同於 MEDIUMINT
的欄位。
$table->mediumInteger('votes');
mediumText()
mediumText
方法會建立一個等同於 MEDIUMTEXT
的欄位。
$table->mediumText('description');
當使用 MySQL 或 MariaDB 時,您可以將 binary
字元集套用到該欄位,以便建立等同於 MEDIUMBLOB
的欄位。
$table->mediumText('data')->charset('binary'); // MEDIUMBLOB
morphs()
morphs
方法是一種便利方法,它會新增一個等同於 {column}_id
的欄位和一個等同於 {column}_type
VARCHAR
的欄位。{column}_id
的欄位類型將會是 UNSIGNED BIGINT
、CHAR(36)
或 CHAR(26)
,取決於模型鍵類型。
此方法旨在用於定義多型 Eloquent 關聯所需的欄位。在以下範例中,將會建立 taggable_id
和 taggable_type
欄位。
$table->morphs('taggable');
nullableTimestamps()
nullableTimestamps
方法是 timestamps 方法的別名。
$table->nullableTimestamps(precision: 0);
nullableMorphs()
此方法與 morphs 方法類似,但建立的欄位將會是「可為空值」。
$table->nullableMorphs('taggable');
nullableUlidMorphs()
此方法與 ulidMorphs 方法類似,但建立的欄位將會是「可為空值」。
$table->nullableUlidMorphs('taggable');
nullableUuidMorphs()
此方法與 uuidMorphs 方法類似,但建立的欄位將會是「可為空值」。
$table->nullableUuidMorphs('taggable');
rememberToken()
rememberToken
方法會建立一個可為空值的 VARCHAR(100)
等效欄位,用於儲存目前的「記住我」身份驗證令牌。
$table->rememberToken();
set()
set
方法會建立一個 SET
等效欄位,並具有給定的有效值列表。
$table->set('flavors', ['strawberry', 'vanilla']);
smallIncrements()
smallIncrements
方法會建立一個自動遞增的 UNSIGNED SMALLINT
等效欄位作為主鍵。
$table->smallIncrements('id');
smallInteger()
smallInteger
方法會建立一個 SMALLINT
等效欄位。
$table->smallInteger('votes');
softDeletesTz()
softDeletesTz
方法會新增一個可為空值的 deleted_at
TIMESTAMP
(帶時區)等效欄位,並可選擇指定秒的小數位數。此欄位旨在儲存 Eloquent 的「軟刪除」功能所需的 deleted_at
時間戳記。
$table->softDeletesTz('deleted_at', precision: 0);
softDeletes()
softDeletes
方法會新增一個可為空值的 deleted_at
TIMESTAMP
等效欄位,並可選擇指定秒的小數位數。此欄位旨在儲存 Eloquent 的「軟刪除」功能所需的 deleted_at
時間戳記。
$table->softDeletes('deleted_at', precision: 0);
string()
string
方法會建立一個具有指定長度的 VARCHAR
等效欄位。
$table->string('name', length: 100);
text()
text
方法會建立一個 TEXT
等效欄位。
$table->text('description');
當使用 MySQL 或 MariaDB 時,您可以將 binary
字元集應用於該欄位,以建立 BLOB
等效欄位。
$table->text('data')->charset('binary'); // BLOB
timeTz()
timeTz
方法會建立一個 TIME
(帶時區)等效欄位,並可選擇指定秒的小數位數。
$table->timeTz('sunrise', precision: 0);
time()
time
方法會建立一個 TIME
等效欄位,並可選擇指定秒的小數位數。
$table->time('sunrise', precision: 0);
timestampTz()
timestampTz
方法會建立一個 TIMESTAMP
(帶時區)等效欄位,並可選擇指定秒的小數位數。
$table->timestampTz('added_at', precision: 0);
timestamp()
timestamp
方法會建立一個 TIMESTAMP
等效欄位,並可選擇指定秒的小數位數。
$table->timestamp('added_at', precision: 0);
timestampsTz()
timestampsTz
方法會建立 created_at
和 updated_at
TIMESTAMP
(帶時區)等效欄位,並可選擇指定秒的小數位數。
$table->timestampsTz(precision: 0);
timestamps()
timestamps
方法會建立 created_at
和 updated_at
TIMESTAMP
等效欄位,並可選擇指定秒的小數位數。
$table->timestamps(precision: 0);
tinyIncrements()
tinyIncrements
方法會建立一個自動遞增的 UNSIGNED TINYINT
等效欄位作為主鍵。
$table->tinyIncrements('id');
tinyInteger()
tinyInteger
方法會建立一個 TINYINT
等效欄位。
$table->tinyInteger('votes');
tinyText()
tinyText
方法會建立一個 TINYTEXT
等效欄位。
$table->tinyText('notes');
當使用 MySQL 或 MariaDB 時,您可以將 binary
字元集應用於該欄位,以建立 TINYBLOB
等效欄位。
$table->tinyText('data')->charset('binary'); // TINYBLOB
unsignedBigInteger()
unsignedBigInteger
方法會建立一個 UNSIGNED BIGINT
等效欄位。
$table->unsignedBigInteger('votes');
unsignedInteger()
unsignedInteger
方法會建立一個 UNSIGNED INTEGER
等效欄位。
$table->unsignedInteger('votes');
unsignedMediumInteger()
unsignedMediumInteger
方法會建立一個 UNSIGNED MEDIUMINT
等效欄位。
$table->unsignedMediumInteger('votes');
unsignedSmallInteger()
unsignedSmallInteger
方法會建立一個 UNSIGNED SMALLINT
等效欄位。
$table->unsignedSmallInteger('votes');
unsignedTinyInteger()
unsignedTinyInteger
方法會建立一個 UNSIGNED TINYINT
等效欄位。
$table->unsignedTinyInteger('votes');
ulidMorphs()
ulidMorphs
方法是一個方便的方法,它會新增一個 {column}_id
CHAR(26)
等效欄位和一個 {column}_type
VARCHAR
等效欄位。
此方法旨在用於定義使用 ULID 識別符的多型 Eloquent 關聯所需的欄位。在以下範例中,將會建立 taggable_id
和 taggable_type
欄位。
$table->ulidMorphs('taggable');
uuidMorphs()
uuidMorphs
方法是一個方便的方法,它會新增一個 {column}_id
CHAR(36)
等效欄位和一個 {column}_type
VARCHAR
等效欄位。
此方法旨在用於定義使用 UUID 識別符的多型 Eloquent 關聯所需的欄位。在以下範例中,將會建立 taggable_id
和 taggable_type
欄位。
$table->uuidMorphs('taggable');
ulid()
ulid
方法會建立一個 ULID
等效欄位。
$table->ulid('id');
uuid()
uuid
方法會建立一個 UUID
等效欄位。
$table->uuid('id');
vector()
vector
方法會建立一個 vector
等效欄位。
$table->vector('embedding', dimensions: 100);
year()
year
方法會建立一個 YEAR
等效欄位。
$table->year('birth_year');
欄位修飾符
除了上面列出的欄位類型之外,您還可以在向資料庫表格新增欄位時使用幾個欄位「修飾符」。例如,若要讓欄位「可為空值」,您可以使用 nullable
方法。
use Illuminate\Database\Schema\Blueprint;use Illuminate\Support\Facades\Schema; Schema::table('users', function (Blueprint $table) { $table->string('email')->nullable();});
下表包含所有可用的欄位修飾符。此列表不包含索引修飾符。
修飾符 | 描述 |
---|---|
->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 欄位指派預設值時,這種情況特別有用。
<?php use Illuminate\Support\Facades\Schema;use Illuminate\Database\Schema\Blueprint;use Illuminate\Database\Query\Expression;use Illuminate\Database\Migrations\Migration; return new class extends Migration{ /** * Run the migrations. */ public function up(): void { Schema::create('flights', function (Blueprint $table) { $table->id(); $table->json('movies')->default(new Expression('(JSON_ARRAY())')); $table->timestamps(); }); }};
對預設運算式的支援取決於您的資料庫驅動程式、資料庫版本和欄位類型。請參閱您的資料庫文件。
欄位順序
當使用 MariaDB 或 MySQL 資料庫時,after
方法可用於在架構中現有欄位之後新增欄位。
$table->after('password', function (Blueprint $table) { $table->string('address_line1'); $table->string('address_line2'); $table->string('city');});
修改欄位
change
方法允許您修改現有欄位的類型和屬性。例如,您可能希望增加 string
欄位的大小。為了展示 change
方法的作用,讓我們將 name
欄位的大小從 25 增加到 50。為了完成此操作,我們只需定義欄位的新狀態,然後呼叫 change
方法。
Schema::table('users', function (Blueprint $table) { $table->string('name', 50)->change();});
修改欄位時,您必須明確包含您要保留在欄位定義上的所有修飾符 - 任何遺失的屬性都將被刪除。例如,若要保留 unsigned
、default
和 comment
屬性,您必須在變更欄位時明確呼叫每個修飾符。
Schema::table('users', function (Blueprint $table) { $table->integer('votes')->unsigned()->default(1)->comment('my comment')->change();});
change
方法不會變更欄位的索引。因此,您可以在修改欄位時使用索引修飾符來明確新增或刪除索引。
// Add an index...$table->bigIncrements('id')->primary()->change(); // Drop an index...$table->char('postal_code', 10)->unique(false)->change();
重新命名欄位
若要重新命名欄位,您可以使用架構產生器提供的 renameColumn
方法。
Schema::table('users', function (Blueprint $table) { $table->renameColumn('from', 'to');});
刪除欄位
若要刪除欄位,您可以在架構產生器上使用 dropColumn
方法。
Schema::table('users', function (Blueprint $table) { $table->dropColumn('votes');});
您可以透過將欄位名稱陣列傳遞給 dropColumn
方法,從表格中刪除多個欄位。
Schema::table('users', function (Blueprint $table) { $table->dropColumn(['votes', 'avatar', 'location']);});
可用的命令別名
Laravel 提供了幾個與刪除常見類型欄位相關的便利方法。每個方法都將在下表中說明。
命令 | 描述 |
---|---|
$table->dropMorphs('morphable'); |
刪除 morphable_id 和 morphable_type 欄位。 |
$table->dropRememberToken(); |
刪除 remember_token 欄位。 |
$table->dropSoftDeletes(); |
刪除 deleted_at 欄位。 |
$table->dropSoftDeletesTz(); |
dropSoftDeletes() 方法的別名。 |
$table->dropTimestamps(); |
刪除 created_at 和 updated_at 欄位。 |
$table->dropTimestampsTz(); |
dropTimestamps() 方法的別名。 |
索引
建立索引
Laravel 架構產生器支援幾種索引類型。以下範例會建立一個新的 email
欄位,並指定其值應是唯一的。若要建立索引,我們可以將 unique
方法鏈接到欄位定義。
use Illuminate\Database\Schema\Blueprint;use Illuminate\Support\Facades\Schema; Schema::table('users', function (Blueprint $table) { $table->string('email')->unique();});
或者,您可以在定義欄位後建立索引。若要執行此操作,您應該在架構產生器藍圖上呼叫 unique
方法。此方法接受應接收唯一索引的欄位名稱。
$table->unique('email');
您甚至可以將欄位陣列傳遞給索引方法以建立複合(或組合)索引。
$table->index(['account_id', 'created_at']);
當建立索引時,Laravel 會根據資料表、欄位名稱和索引類型自動產生索引名稱,但您可以將第二個參數傳遞給方法來自行指定索引名稱
$table->unique('email', 'unique_email');
可用的索引類型
Laravel 的 Schema Builder Blueprint 類別提供了建立 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 除外)。 |
重新命名索引
要重新命名索引,您可以使用 Schema Builder Blueprint 提供的 renameIndex
方法。此方法接受目前的索引名稱作為其第一個參數,並將所需的名稱作為其第二個參數
$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 除外)。 |
如果您將欄位陣列傳遞給刪除索引的方法,將會根據資料表名稱、欄位和索引類型產生慣用的索引名稱
Schema::table('geo', function (Blueprint $table) { $table->dropIndex(['state']); // Drops index 'geo_state_index'});
外鍵約束
Laravel 也支援建立外鍵約束,用於在資料庫層級強制參照完整性。例如,讓我們在 posts
資料表上定義一個 user_id
欄位,該欄位參照 users
資料表上的 id
欄位
use Illuminate\Database\Schema\Blueprint;use Illuminate\Support\Facades\Schema; Schema::table('posts', function (Blueprint $table) { $table->unsignedBigInteger('user_id'); $table->foreign('user_id')->references('id')->on('users');});
由於此語法相當冗長,Laravel 提供了額外的、更簡潔的方法,這些方法使用慣例來提供更好的開發人員體驗。當使用 foreignId
方法建立您的欄位時,上面的範例可以改寫如下
Schema::table('posts', function (Blueprint $table) { $table->foreignId('user_id')->constrained();});
foreignId
方法建立一個等效的 UNSIGNED BIGINT
欄位,而 constrained
方法將使用慣例來判斷正在參照的資料表和欄位。如果您的資料表名稱與 Laravel 的慣例不符,您可以手動將其提供給 constrained
方法。此外,也可以指定應該指派給所產生索引的名稱
Schema::table('posts', function (Blueprint $table) { $table->foreignId('user_id')->constrained( table: 'users', indexName: 'posts_user_id' );});
您也可以為約束的 "on delete" 和 "on update" 屬性指定所需的操作
$table->foreignId('user_id') ->constrained() ->onUpdate('cascade') ->onDelete('cascade');
這些操作也提供了另一種具表達性的語法
方法 | 描述 |
---|---|
$table->cascadeOnUpdate(); |
更新應級聯。 |
$table->restrictOnUpdate(); |
更新應受限制。 |
$table->nullOnUpdate(); |
更新應將外鍵值設定為 null。 |
$table->noActionOnUpdate(); |
更新時不採取任何動作。 |
$table->cascadeOnDelete(); |
刪除應級聯。 |
$table->restrictOnDelete(); |
刪除應受限制。 |
$table->nullOnDelete(); |
刪除應將外鍵值設定為 null。 |
$table->noActionOnDelete(); |
如果存在子記錄,則防止刪除。 |
任何額外的 欄位修飾符 都必須在 constrained
方法之前呼叫
$table->foreignId('user_id') ->nullable() ->constrained();
刪除外鍵
要刪除外鍵,您可以使用 dropForeign
方法,將要刪除的外鍵約束名稱作為參數傳遞。外鍵約束使用與索引相同的命名慣例。換句話說,外鍵約束名稱基於資料表的名稱和約束中的欄位,後接 "_foreign" 後綴
$table->dropForeign('posts_user_id_foreign');
或者,您可以將包含保存外鍵的欄位名稱的陣列傳遞給 dropForeign
方法。該陣列將使用 Laravel 的約束命名慣例轉換為外鍵約束名稱
$table->dropForeign(['user_id']);
切換外鍵約束
您可以使用以下方法在遷移中啟用或停用外鍵約束
Schema::enableForeignKeyConstraints(); Schema::disableForeignKeyConstraints(); Schema::withoutForeignKeyConstraints(function () { // Constraints disabled within this closure...});
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 |
已載入現有的資料庫結構描述轉儲。 |