這幾個月開始寫 Laravel 跟 Codeigniter 是真的差滿多的,開始需要一些時間適應跟學習新東西,但習慣之後就會發現 Laravel 能讓開發效率提升不少,也比較能理解主流的開發模式。

Laravel 的 Migrations 就是用來管理資料庫的一種方式,像我用慣 Workbench 一開始真的不習慣這種方式,但在多人開發的情況下,勢必是要使用 Migrations 的,我只要把 Code Pull 下來,執行一下 Migrations,就可以更新到最新的資料庫結構,實在是非常方便,寫習慣之後會發現比直接操作資料庫快!

我是在 Windows 的環境開發,Command 的部份用 Power Shell,Migrations 的基本指令


# 建立一個 Migrations 檔案,可以建立 Table
php artisan make:migration create_users_table

# 一樣是建立 Migrations,但是是用來調整 Table
php artisan make:migration change_some_column --table=table_name

# 執行 Migrations
php artisan migrate

# 還原 Migrations
php artisan migrate:rollback

# 還原 Migrations 並指定步數
php artisan migrate:rollback --step=5

因為我們是中途才開始使用 Migrations 所以有同事用這支 Migrations Generator 對所有的資料表建立了 Migrations 檔案,但因為還沒時間來處理這個動作,所以我們只好把實際需要執行的 Migration 搬到別的資料夾中,Migrations 指令可以指定要執行的路徑:


# 指定 Path
php artisan migrate --path=/database/migrations/selected/

# Rollback
php artisan migrate:rollback --step=3 --path=/database/migrations/selected/

操作上大概如此,接下來我們看看實際撰寫的方式:


class CreateSalesPerformance extends Migration
{
    # 執行的 Function
    public function up()
    {
        # 如果 Table 已經存在就先 Drop
        Schema::dropIfExists('sales_performance');

        # 建立 Table
        Schema::create('sales_performance', function (Blueprint $table) {
            # 建立一個名為 id ( 主鍵 )的 auto increments 欄位
            $table->increments('id');
            # 建立一個名為 order 的欄位,型態為 varchar 長度 30
            $table->string('order', 30);
            # 建立一個名為 amount 的欄位,型態為 Unsigned INT
            $table->unsignedInteger('amount');
            # 建立一個名為 sales 的欄位,並加上預設數值
            $table->unsignedInteger('sales')->default($value);
            # 建立一個名為 employee 的欄位,允許空值
            $table->string('employee', 100)->nullable();
            # 建立一個名為 verify 的欄位,並寫入註解
            $table->unsignedInteger('verify')->comment('my comment');
            # 建立索引
            $table->index(['order', 'employee']);
        });
        # 幫Table 寫入註解
        DB::statement("ALTER TABLE `sales_performance` comment '業績紀錄表'");
    }

    public function down()
    {
        # rollback 時要執行的部分
        Schema::dropIfExists('cs_sales_performance');
    }
}

接著我們試試看如何調整已經存在的資料庫欄位


class ChangeSalesPerformance extends Migration
{
    public function up()
    {
        Schema::table('sales_performance', function (Blueprint $table) {
            # 在 amount 欄位後加上 installments 欄位
            $table->unsignedInteger('installments')->after('amount');
            # 變更 emplyee 欄位的長度
            $table->string('employee', 200)->change();
        });
    }

    public function down()
    {
        Schema::table('sales_performance', function (Blueprint $table) {
            # rollback 的時候刪除欄位
            $table->dropColumn('installments');
            # rollback 的時候還原長度
            $table->string('employee', 100)->change();
        });
    }
}

以上就是比較常用的寫法,更詳細的用法就參考官網手冊囉,Laravel 5.5 的數據庫遷移

另外再使用的時候我碰到一個問題,我在 rollback 底下這個 Migrations 的時候碰到錯誤


class ChangeSalesPerformance extends Migration
{

    public function up()
    {
        Schema::table('sales_performance', function (Blueprint $table) {
            $table->string('installments', 10);
            $table->index('installments');
        });
    }

    public function down()
    {
        Schema::table('sales_performance', function (Blueprint $table) {
            $table->dropColumn('installments');
            $table->dropIndex('installments');
        });
    }
}

錯誤訊息是找不到欄位,雖然 migrate 報錯,但欄位還是被刪掉了,這就會造成 DB 跟 Migrations 不同步的狀況,沒有辦法 Rollback 也沒有辦法執行,這時候只能去 migration 資料表,把這筆紀錄刪掉,再重新執行!