Laravel 8.37 的新功能,匿名 Migration
這個功能的想法起因於某個 Laravel 的 issue,這個 issue 描述了一個問題。
問題中描述的狀況是:
- 在專案版本 1.0 的時候建立一個 migration,名稱為
create_new_table
。 - 在專案版本 1.1 的時候建立一個 migration,名稱為
drop_new_table
去移除 new table。 - 在專案版本 2.0 的時候建立一個 migration,名稱為
create_new_table
,與第一步的名稱相同。
簡而言之,因為不同 migration 中擁有相同的 class 名稱導致執行 migrate 建立資料表時發生錯誤。
雖然 migration 檔名前面會加上日期防止檔名完全相同,但是 class 名稱並不會這麼做。例如下面這兩個 migration 檔案,class name 都會是 CreateNewTable
。
2020_06_15_220259_create_new_table.php
2021_03_11_114229_create_new_table.php
在後來的 PR (#36906) 中,有人提出一個解決辦法。使用 PHP 的 Anonymous classes 來解決這個問題。
下方是匿名 migration 的範例:
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
// 沒有名稱的 class
return new class extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('people', function (Blueprint $table) {
$table->string('first_name')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('people', function (Blueprint $table) {
$table->dropColumn('first_name');
});
}
};
匿名 migration 在 8.37 中正式支援。Laravel 官方有在考慮 migration 預設是否要直接使用匿名 class。因為屬於 Breaking change,有可能在 Laravel 9 中才會變成預設設定。
如果希望指令預設直接生成匿名 migration ,官方提到可以手動修改 stub 檔案,首先在專案中輸入指令,生成 stubs 資料夾。
php artisan stub:publish
修改 stubs 資料夾底下的三個檔案:
migration.create.stub
migration.stub
migration.update.stub
// 將三個 stub 檔案中原本的 class name 設定
class {{ class }} extends Migration
{
...
}
// 改為使用匿名 class
return new class extends Migration
{
...
// 大括弧後面要加上 ";"
};
這時輸入指令 make:migration
就會看到新生成的 migration 檔案使用匿名 class。