學習Laravel Migration,看這一篇就夠了

學習Laravel Migration,看這一篇就夠了

Migration 就像是對資料庫進行的版本控制,讓你的團隊能夠輕鬆地去定義和共享應用的資料庫結構。Migration 通常配合 Laravel 的結構(Schema)生成器,可以輕鬆生成應用的資料庫結構。如果團隊中有個成員在他本地的資料庫環境中手動的添加了新欄位,那麼團們將會面對如何解決數據庫結構調整的問題

好消息是 Laravel 的 Schema facade 提供了資料庫相關的支持,可以在所有 Laravel 支持的資料庫管理系統中創建和操作表格

在這個章節我將會反覆地提到 Migration 以及 Migrate,對於新人來說不免覺得有些困惑。其實很簡單,這裡我給出說明

Migration 是名詞,代表的是準備用來變更資料庫結構的檔案,但本身無法執行。 Migrate 是動詞,它是用來執行 Migration 的內容。你搞懂了嗎?

生成 Migration 檔案

可以使用 make:migration Artisan 命令來建立 Migration 檔案。新的 Migration 文件將會放在 database/migrations 資料夾底下。 所有的 Migration 文件名稱都會包含一個時間戳記,Laravel 將據此來決定哪個 Migration 檔案要先被執行運行

php artisan make:migration create_flights_table

有意思的是, Laravel 將會使用 Migration 的檔名來猜測對應表格的名稱以及是否該 Migration 的主要目的是否為建立新表格。假如 Laravel 覺得已經能根據檔名猜出表格名稱的話,它就會為你預填好該表格的內容到 Migration 檔案內。要是檔案名稱沒有按照慣例來取的話,就需要你自己手動的填入表格名稱等結構內容

小技巧

假如你想將 Migration 檔案生成在自定義的路徑上的話,能在呼叫 make:migration 命令時使用 --path選項,該路徑須相對於專案根目錄

進階小技巧

你可以使用 stub 發布的技巧來自定義 Migration 的 stub

Migration 合併(進階技巧)

隨着時間,應用中的 Migration 會積累的越來越多。使得資料夾變得臃腫,甚至會有數百個 Migration 文件。所以如果你願意,可以將若干個 Migration 檔案,壓縮到單個 SQL 檔案中。進行這個操作,需要執行的命令是:schema:dump

完整的命令如下:

//合併但不刪除原有 Migration 文件
`php artisan schema:dump`

//合併且刪除原有 Migration 文件
php artisan schema:dump --prune

在執行以上命令後,laravel 將會把合併後的 SQL 檔案,放到專案的 database/schema 資料夾中

在進行合併操作後,當嘗試進行 migrate 操作時,在未指定 Migration 文件的預設情況下,Laravel 將會首先執行 SQL 檔案的內容。在執行 SQL 文件後,Laravel 將會繼續執行其他 Migration 檔案

Migration 的核心作用是使團隊中的其他開發人員,可以快速的創建該應用的初始資料庫結構。 所以在完成應用的資料庫架構修改後,也應該將資料庫架構文件提交至程式碼管理員、專案負責人或是 Git 版本控管平台,這能大大提高應用團隊的效率和協同能力

注意: Migration 合併功能僅適用於 MySQL,PostgreSQL 和 SQLite 資料庫,而且 SQLite還限定為非 in-memory

Migration 結構

Migration 檔案內有兩個方法: up() 和 down()。 up() 的作用是向資料庫中添加新的表格或欄位或索引,也就是這個 Migration 的主要目的。而 down() 的方法則是 up() 的反向操作,用來還原到執行 up() 之前的資料庫狀態

在這兩種方法中,你可以使用 Laravel 的 Schema 生成器很方便地去創建和修改表格。要了解 Schema 生成器上可用的所有方法,請查看相關單元

這邊來看一下,此 Migration 將創建一個 flights 表格:

//database\migrations\CreateFlightsTable.php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateFlightsTable extends Migration
{
    //向資料庫中添加新的 flights 表格
    public function up()
    {
        Schema::create('flights', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('airline');
            $table->timestamps();
        });
    }

    //還原 up() 的操作,也就是刪除 flights 表格
    public function down()
    {
        Schema::drop('flights');
    }
}

設定 Migration 連線(進階技巧)

假如你的 Migration 在執行時希望不要使用預設的資料庫連線而是其他備選資料庫的話,你可以透過在 Migration 檔案內設定 $connectoin 來達到

所有的資料庫連線都被設定於 config/database.php 檔案內

//指定該 Migration 要改用名為 pgsql 的資料庫連線

//database\migrations\CreateFlightsTable.php
protected $connection = 'pgsql';

執行 Migrate

要執行所有還未執行的 Migration ,只需執行以下的 Artisan 命令

php artisan migrate

假如你想知道到目前有哪些 Migration 已經執行完畢,你可以使用 migrate:status 指令又或者去看 migrations 表格都是一樣的

php artisan migrate:status

在正式環境中強制執行 Migrate

有些 Migrate 操作是有破壞性的,這意味着它們可能會導致資料消失。為了防止你不小心對生式資料庫運行這些命令,在執行這些命令之前,系統將提示你進行最後確認。如果要在運行強制命令的時候去掉提示,請使用 -force 選項:

php artisan migrate --force

還原 Migration

要返回到最後一次操作,你可以使用 rollback 命令。此命令會返回到最後 「一批」 的 Migration 狀態,這操作可能會包含多個位於同一批的 Migration 文件:

它實作還原的作法是甚麼? 就是呼叫你所實作的 down(),搞明白了嗎?

php artisan migrate:rollback

如果在 rollback 命令的後面加上 step 選項,可以指定要還原的 Migration 數量。例如,以下命令將還原最後 5 個 Migration:

php artisan migrate:rollback --step=5

migrate:reset 是最具破壞力的一種操作,它將會還原應用中所有的 Migration

一鍵同時進行還原與 Migrate

使用 migrate:refresh 命令將會還原所有 Migration 操作,然後 Laravel 將繼續執行 migrate 命令以進行重新 Migrate。同時可在該命令後加上 --seed, 這個選項的作用是在 「刷新」 完成數據庫之後,順便執行 Seed 以生成資料

如需使用 Seed 功能,你還必須自己實作各表格的 Seeder 類別

範例:

//重置所有 Migration
php artisan migrate:refresh

//重置所有 Migration 並同時建立資料
php artisan migrate:refresh --seed

之前所介紹過的 --step 選項,在這裡同樣適用,請參考這個例子

//重置 5 個 Migration 檔案
php artisan migrate:refresh --step=5

資料表

建立資料表

我們將示範用 Schema 生成器的 create() 來創建一個新的資料表。 create() 中可以接受兩個參數,一個是表格的名稱,第二個是 Closure,作用是可以在定義新資料表的時候得到 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();
});

有了 Blueprint 物件,你就能用它的各種欄位方法來定義表格裡的欄位

確認表格 & 欄位是否存在

你能使用 hasTable 以及 hasColumn 方法來確認表格或欄位是否存在

if (Schema::hasTable('users')) {
    // "users" 表格存在...
}

if (Schema::hasColumn('users', 'email')) {
    // "users" 表格存在並包含 "email" 欄位...
}

資料庫連接 & 表格選項

如果要對非預設連接的資料庫連接執行結構操作,可以使用 connection():

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

你也可以在 Schema 生成器上使用以下作法來定義表格的選項,比如當使用 MySQL 時的 storage engine:

Schema::create('users', function (Blueprint $table) {
    $table->engine = 'InnoDB';
    $table->charset = 'utf8mb4';
    $table->collation = 'utf8mb4_unicode_ci';

    // ...
});
屬性操作 說明
$table->engine = 'InnoDB'; 指定表格儲存引擎 (MySQL)
$table->charset = 'utf8mb4'; 指定資料表的預設字符集 (MySQL)
$table->collation = 'utf8mb4_unicode_ci'; 指定資料表預設的排序規則 (MySQL)
$table->temporary(); 創建臨時表格 (不支持 SQL Server)

更新表格

Schema facade 的 table() 用於更新已有的表格。就像 create() ,它接受兩個參數: 表格名稱以及 Closure。而 Closure 同樣會得到 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()

//一定要刪到 users 表格
Schema::drop('users');

//如果 users 表格存在才刪除
Schema::dropIfExists('users');

重命名帶外鍵關係的資料表(進階知識)

在重命名表格之前,你應該確認表格上的任何外鍵關係在 Migration 文件中都有明確的名稱,而不是讓 Laravel 按照預設來設置一個名稱。否則外鍵的關係名稱將引用舊表格名

欄位

建立欄位

之前有說過,你能夠利用 Closure 所得到的 Illuminate\Database\Schema\Blueprint 實例來建立表格欄位:

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

Schema::table('users', function (Blueprint $table) {
    $table->integer('votes');
});

可使用的欄位類型

資料庫 Schema 生成器包含表格常用的各種欄位類型,如下所列:

程式碼 說明
$table->id(); $table->bigIncrements('id') 的別名
$table->foreignId('user_id'); $table->unsignedBigInteger('user_id') 的別名
$table->bigIncrements('id'); 遞增 ID(主鍵),相當於「UNSIGNED BIG INTEGER」
$table->bigInteger('votes'); 相當於 BIGINT
$table->binary('data'); 相當於 BLOB
$table->boolean('confirmed'); 相當於 BOOLEAN
$table->char('name', 100); 相當於帶有長度的 CHAR
$table->date('created_at'); 相當於 DATE
$table->dateTime('created_at', 0); 相當於 DATETIME ,可以指定位數
$table->dateTimeTz('created_at', 0); 相當於 DATETIME (帶時區) ,可以指定位數
$table->decimal('amount', 8, 2); 相當於 DECIMAL,可以指定總位數和小數位數
$table->double('amount', 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 MEDIUMINT
$table->mediumInteger('votes'); 相當於 MEDIUMINT
$table->mediumText('description'); 相當於 MEDIUMTEXT
$table->morphs('taggable'); 相當於加入遞增 UNSIGNED BIGINT 類型的 taggable_id 與字串類型的 taggable_type
$table->uuidMorphs('taggable'); 相當於添加一個 CHAR (36) 類型的 taggable_id 欄位和 VARCHAR (255) UUID 類型的 taggable_type
$table->multiLineString('positions'); 相當於 MULTILINESTRING
$table->multiPoint('positions'); 相當於 MULTIPOINT
$table->multiPolygon('positions'); 相當於 MULTIPOLYGON
$table->nullableMorphs('taggable'); 添加一個可以為空版本的 morphs() 欄位
$table->nullableUuidMorphs('taggable'); 添加一個可以為空版本的 uuidMorphs() 欄位
$table->nullableTimestamps(0); timestamps() 方法的別名
$table->point('position'); 相當於 POINT
$table->polygon('positions'); 相當於 POLYGON
$table->rememberToken(); 添加一個允許空值的 VARCHAR (100) 類型的 remember_token 欄位
$table->set('flavors', ['strawberry', 'vanilla']); 相當於 SET
$table->smallIncrements('id'); 遞增 ID(主鍵),相當於 UNSIGNED SMALLINT
$table->smallInteger('votes'); 相當於 SMALLINT
$table->softDeletes('deleted_at', 0); 相當於為軟刪除添加一個可為空值的 deleted_at 欄位
$table->softDeletesTz('deleted_at', 0); 相當於為軟刪除添加一個可為空值的帶時區的 deleted_at 欄位
$table->string('name', 100); 相當於指定長度的 VARCHAR
$table->text('description'); 相當於 TEXT
$table->time('sunrise', 0); 相當於指定位數的 TIME
$table->timeTz('sunrise', 0); 相當於指定位數帶時區的 TIME
$table->timestamp('added_on', 0); 相當於指定位數的時間戳記
$table->timestampTz('added_on', 0); 相當於指定位數帶時區的時間戳記
$table->timestamps(0); 相當於添加可為空值的時間戳記類型的 created_at 和 updated_at
$table->timestampsTz(0); 相當於添加指定時區的可為空值的時間戳記類型的 created_at 和 updated_at
$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 INTEGER
$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():

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

Schema::table('users', function (Blueprint $table) {
    $table->string('email')->nullable();
});

以下是所有可用的欄位修飾子的列表,不包括索引修飾子:

修飾子 說明
->after('column') 將此欄位放置在其它欄位 「之後」 (MySQL)
->autoIncrement() 將 INTEGER 類型的欄位設置為自動遞增的主鍵
->charset('utf8mb4') 指定一個字符集 (MySQL)
->collation('utf8mb4_unicode_ci') 指定排序規則 (MySQL/PostgreSQL/SQL Server)
->comment('my comment') 為欄位增加注釋 (MySQL/PostgreSQL)
->default($value) 為欄位指定 「預設」 值
->first() 將此欄位放置在數據表的 「首位」 (MySQL)
->from($integer) 給自增欄位設置一個起始值 (MySQL / PostgreSQL)
->nullable($value = true) 此欄位允許寫入 NULL 值(預設情況下)
->storedAs($expression) 創建一個存儲生成的欄位 (MySQL)
->unsigned() 設置 INTEGER 類型的欄位為 UNSIGNED (MySQL)
->useCurrent() 將 TIMESTAMP 類型的欄位設置為使用 CURRENT_TIMESTAMP 作為預設值
->virtualAs($expression) 創建一個虛擬生成的欄位 (MySQL)
->generatedAs($expression) 使用指定的序列生成標識列(PostgreSQL)
->always() 定義序列值優先於標識列的輸入 (PostgreSQL)

default 修飾子接收一個變數或者一個 \Illuminate\Database\Query\Expression 實例。使用 Expression 實例可以避免使用包含在引號中的值,並且允許你使用特定資料庫函數。這在當你需要給 JSON 欄位指定預設值的時候特別有用:

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Query\Expression;
use Illuminate\Database\Migrations\Migration;

class CreateFlightsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('flights', function (Blueprint $table) {
            $table->id();
            $table->json('movies')->default(new Expression('(JSON_ARRAY())'));
            $table->timestamps();
        });
    }
}

注意:

支持哪些預設值的 Expression 表示方式取決於你的資料庫驅動、版本、還有欄位類型,使用前請先詳閱資料庫公開說明書

欄位順序(進階技巧)

如果你使用的是 MySQL 資料庫,after() 用來讓你將新定義的欄位擺在已存在的表格欄位之後:

$table->after('password', function ($table) {
    $table->string('address_line1');
    $table->string('address_line2');
    $table->string('city');
});

修改欄位

前置準備

如需修改欄位,請確保將 doctrine/dbal 套件安裝到專案內。Doctrine DBAL 套件用於確定欄位的當前狀態, 並創建對該欄位進行指定調整所需的 SQL 查詢,以下是安裝套件的指令:

composer require doctrine/dbal

假如你準備修改原本是用 timestamp() 所生成的欄位,你需要加入以下的設定到應用的資料庫設定檔 config/database.php

//config\database.php

use Illuminate\Database\DBAL\TimestampType;

'dbal' => [
    'types' => [
        'timestamp' => TimestampType::class,
    ],
],

假如你的應用使用的是 Microsoft SQL Server,請確保有安裝 doctrine/dbal:^3.0 版本

更新欄位屬性

change() 方法可以將現有的欄位類型修改為新的類型或修改它的屬性。比如,你可能想增加字串欄位的長度,可以使用 change() 把 name 欄位的長度從 25 增加到 50:

Schema::table('users', function (Blueprint $table) {
    $table->string('name', 50)->change(); //把欄位長度改為50
});

Schema::table('users', function (Blueprint $table) {
    $table->string('name', 50)->nullable()->change(); //把欄位改為可為空值
});

注意:

只有以下欄位類型能被修改:bigInteger、binary、boolean、date、dateTime、dateTimeTz、decimal、integer、json、 longText、mediumText、smallInteger、string、text、time、unsignedBigInteger、unsignedInteger 和 unsignedSmallInteger 以及 uuid。如果要修改 timestamp 欄位需要先註冊 Doctrine 類型

欄位更名

可以使用 Schema 生成器上的 renameColumn() 來重命名欄位。在重命名欄位前,請確保你的應用已經下載過 doctrine/dbal 套件,可透過檢查 composer.json 文件來確認:

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

注意:

目前版本不支持 enum 類型的欄位重命名

欄位刪除

可以使用 Schema 生成器上的 dropColumn() 方法來刪除欄位,同樣需要 doctrine/dbal 套件:

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

你可以傳遞一個字串陣列給 dropColumn() 來一次刪除多個欄位:

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

注意:

使用 SQLite 資料庫時不支持在單個 Migration 中刪除或修改多個欄位

可用的命令別名

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() 方法別名

索引

建立索引

Schema 生成器支持多種類型的索引。下面的例子中新建了一個值唯一的 email 欄位。我們可以將 unique() 串到欄位定義後面來創建索引:

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

Schema::table('users', function (Blueprint $table) {
    $table->string('email')->unique();
});

或者,你也可以在定義完欄位之後創建索引。例如:

$table->unique('email');

你甚至可以將陣列傳遞給索引方法來創建一個複合索引:

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

Laravel 會自動生成一個合理的索引名稱,但你也可以傳遞第二個參數來自定義索引名稱:

$table->unique('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 或者版本低於 10.2.2 的 MariaDB 上創建索引,那你就需要手動配置 Migration 的預設字串長度。

作法就是在 AppServiceProvider 中調用 Schema::defaultStringLength() 來配置它:

//app\Providers\AppServiceProvider.php
use Illuminate\Support\Facades\Schema;

public function boot()
{
    Schema::defaultStringLength(191);
}
重命名索引

若要重命名索引,你需要呼叫 Schema 生成器的 blueprint 物件所提供的 renameIndex()。此方法接受當前索引名稱作為其第一個參數,並將所需名稱作為其第二個參數:

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

刪除索引

若要刪除索引,則必須指定索引的名稱。Laravel 預設會自動將資料表名稱、索引的欄位名及索引類型簡單地連接在一起作為名稱。舉例如下:

命令 說明
$table->dropPrimary('users_id_primary'); 從 「users」 表中刪除主鍵
$table->dropUnique('users_email_unique'); 從 「users」 表中刪除 unique 索引
$table->dropIndex('geo_state_index'); 從 「geo」 表中刪除基本索引
$table->dropSpatialIndex('geo_location_spatialindex'); 從 「geo」 表中刪除空間索引(不支持 SQLite)

如果將字串陣列傳給 dropIndex() ,會刪除根據表格名稱、欄位和索引類型生成的索引名稱

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

外鍵約束

Laravel 還支持創建用於在資料庫層中的強制引用完整性的外鍵約束。例如,讓我們在 posts 表格上定義一個參考到 users 表格的 id 欄位的 user_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 額外提供了更簡潔的方法來提供更好的開發人員體驗,因此上面的範例還可以這麼寫:

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

foreignId() 是 unsignedBigInteger 的別名,而 constrained() 將使用命名慣例來確定所參考的表格名和欄位名。如果表格名與命名慣例不匹配,可以通過將表格名作為參數傳遞給 constrained() 來指定表格名:

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

你也可以為外鍵約束的「on delete」和「on update」屬性指定所需的操作:

$table->foreignId('user_id')
      ->constrained()
      ->onUpdate('cascade')
      ->onDelete('cascade');

如果有需要使用其他的欄位修飾子時,務必在呼叫 constrained() 之前先呼叫:

$table->foreignId('user_id')
      ->nullable()
      ->constrained();
刪除外鍵

要刪除一個外鍵,你需要使用 dropForeign() ,將要刪除的外鍵約束作為參數傳遞。外鍵約束採用的命名方式與索引相同。即將資料表名稱和約束的欄位連接起來,再加上 "_foreign" 後綴:

$table->dropForeign('posts_user_id_foreign');

或者,可以給 dropForeign() 傳遞一個陣列,該陣列包含要刪除的外鍵的欄位名。陣列將根據 Laravel 的 Schema 生成器使用的約束名稱約定自動轉換:

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

你可以在 Migration 中使用以下方法來開啟或關閉外鍵約束:

Schema::enableForeignKeyConstraints();

Schema::disableForeignKeyConstraints();

注意:

SQLite 預設禁用外鍵約束。使用 SQLite 時,請確保在資料庫配置中啟用"啟用外鍵支持",然後再嘗試在 Migration 中創建它們。另外,SQLite 只在創建表格時支持外鍵,並且在修改表格時就不會了


分享這篇文章:
 

關聯文章: