展開文件目錄

資料庫:Seeding

簡介

Laravel 包含使用 Seeder 類別為資料庫填充測試資料的功能。所有的 Seeder 類別都儲存在 database/seeders 目錄中。預設情況下,已經為你定義了一個 DatabaseSeeder 類別。在此類別中,你可以使用 call 方法來執行其他的 Seeder 類別,讓你能夠控制填充的順序。

[!NOTE] 在資料庫填充期間,批量賦值保護 (Mass assignment protection) 會自動禁用。

撰寫 Seeder

要生成一個 Seeder,請執行 make:seeder Artisan 指令。所有由框架生成的 Seeder 都會被放置在 database/seeders 目錄中:

php artisan make:seeder UserSeeder

預設情況下,Seeder 類別只包含一個方法:run。當執行 db:seed Artisan 指令時,就會呼叫此方法。在 run 方法中,你可以隨意將資料插入資料庫。你可以使用 查詢產生器 (Query Builder) 手動插入資料,或者也可以使用 Eloquent Model Factory

舉例來說,讓我們修改預設的 DatabaseSeeder 類別,並在 run 方法中加入一個資料庫插入陳述式:

<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;

class DatabaseSeeder extends Seeder
{
    /**
     * 執行資料庫 Seeder。
     */
    public function run(): void
    {
        DB::table('users')->insert([
            'name' => Str::random(10),
            'email' => Str::random(10).'@example.com',
            'password' => Hash::make('password'),
        ]);
    }
}

[!NOTE] 你可以在 run 方法的參數中使用型別提示任何你需要的依賴。它們將自動透過 Laravel 服務容器 (Service Container) 解析。

使用 Model Factory

當然,手動為每個 Model Seed 指定屬性是很麻煩的。相反地,你可以使用 Model Factory 來方便地生成大量的資料庫紀錄。首先,請閱讀 Model Factory 文件 以了解如何定義你的 Factory。

例如,讓我們建立 50 個使用者,且每個使用者都有一篇相關的貼文:

use App\Models\User;

/**
 * 執行資料庫 Seeder。
 */
public function run(): void
{
    User::factory()
        ->count(50)
        ->hasPosts(1)
        ->create();
}

呼叫其他 Seeder

DatabaseSeeder 類別中,你可以使用 call 方法來執行額外的 Seeder 類別。使用 call 方法可以讓你將資料庫填充拆分成多個檔案,這樣就不會有單一 Seeder 類別過於龐大的問題。call 方法接受一個應執行的 Seeder 類別陣列:

/**
 * 執行資料庫 Seeder。
 */
public function run(): void
{
    $this->call([
        UserSeeder::class,
        PostSeeder::class,
        CommentSeeder::class,
    ]);
}

禁用 Model 事件

在執行 Seeder 時,你可能希望防止 Model 發送事件。你可以使用 WithoutModelEvents Trait 來達成此目的。使用時,WithoutModelEvents Trait 會確保不會發送任何 Model 事件,即使是透過 call 方法執行的額外 Seeder 類別也是如此:

<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;

class DatabaseSeeder extends Seeder
{
    use WithoutModelEvents;

    /**
     * 執行資料庫 Seeder。
     */
    public function run(): void
    {
        $this->call([
            UserSeeder::class,
        ]);
    }
}

執行 Seeder

你可以執行 db:seed Artisan 指令來填充你的資料庫。預設情況下,db:seed 指令會執行 Database\Seeders\DatabaseSeeder 類別,該類別可能會轉而呼叫其他的 Seeder 類別。不過,你可以使用 --class 選項來指定要單獨執行的特定 Seeder 類別:

php artisan db:seed

php artisan db:seed --class=UserSeeder

你也可以使用 migrate:fresh 指令搭配 --seed 選項來填充資料庫,這將會刪除所有資料表並重新執行你所有的 Migration。這個指令對於完整重建資料庫非常有用。可以使用 --seeder 選項來指定要執行的特定 Seeder:

php artisan migrate:fresh --seed

php artisan migrate:fresh --seed --seeder=UserSeeder

在正式環境強制執行 Seeder

某些填充操作可能會導致你更改或遺失資料。為了防止你在正式環境 (Production) 資料庫執行填充指令,在 production 環境執行 Seeder 之前會提示你進行確認。若要強制執行 Seeder 而不顯示提示,請使用 --force 旗標:

php artisan db:seed --force