Laravel 8.37 的新功能,匿名 migration

sharkHead 程式技術 4週前 • 0

起因於某次 Laravel 的 issue(#5899)中提出的一個狀況
問題中描述的狀況是

  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 名稱並不會這麼做

  • 2020_06_15_220259_create_new_table.php
  • 2021_03_11_114229_create_new_table.php

上述兩個 migration 檔案,class name 都會是 CreateNewTable

在後來的 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

 

參考資料
New in Laravel 8.37: Anonymous Migrations with no Class Names
Anonymous Migrations in Laravel 8.37
Anonymous classes


Laravel 與 Python 菜雞工程師
喜愛研究程式相關技術
正在學習 TypeScript 與 Vue.js