Laravel 8.37 的新功能,匿名 Migration

程式技術
sharkHead

這個功能的想法起因於某個 Laravel 的 issue,這個 issue 描述了一個問題。

問題中描述的狀況是:

  1. 在專案版本 1.0 的時候建立一個 migration,名稱為 create_new_table
  2. 在專案版本 1.1 的時候建立一個 migration,名稱為 drop_new_table 去移除 new table。
  3. 在專案版本 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。

參考資料

sharkHead
written by
sharkHead

後端打工仔,在下班後喜歡研究各種不同的技術。稍微擅長 PHP,並偶爾涉獵前端開發。個性就像動態語言般隨興,但渴望做事能像囉嗦的靜態語言那樣嚴謹。

0 則留言