Lzh on GitHub

介绍

Laravel 提供了使用填充类(Seeder)向数据库批量写入数据的功能。所有填充类都存放在 database/seeders 目录下。默认情况下,系统会为你生成一个 DatabaseSeeder 类。你可以在该类中使用 call 方法来运行其他填充类,从而控制填充的顺序。

在数据库填充过程中,Laravel 会自动禁用批量赋值保护(Mass Assignment Protection)。

编写填充器(Seeder)

要生成一个填充类(Seeder),可以执行 Artisan 命令 make:seeder。框架生成的所有填充类都会放置在 database/seeders 目录下:

php artisan make:seeder UserSeeder

一个填充类默认只包含一个方法:run。当执行 db:seed Artisan 命令时,会调用该方法。在 run 方法中,你可以按照自己的需求向数据库插入数据,可以使用查询构建器手动插入,也可以使用 Eloquent 模型工厂。

例如,下面修改默认的 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
{
    /**
     * 运行数据库填充器。
     */
    public function run(): void
    {
        DB::table('users')->insert([
            'name' => Str::random(10),
            'email' => Str::random(10).'@example.com',
            'password' => Hash::make('password'),
        ]);
    }
}
你可以在 run 方法的参数中进行类型提示(type-hint)所需的任何依赖,这些依赖会通过 Laravel 的服务容器自动解析。

使用模型工厂(Model Factory)

当然,为每个模型手动指定属性非常繁琐。相反,你可以使用模型工厂(model factories)来方便地生成大量数据库记录。首先,请参考模型工厂文档,了解如何定义工厂。

例如,下面示例创建 50 个用户,每个用户都有一篇关联的文章:

use App\Models\User;

/**
 * 运行数据库填充器。
 */
public function run(): void
{
    User::factory()
        ->count(50)
        ->hasPosts(1)
        ->create();
}

调用其他填充器

DatabaseSeeder 类中,你可以使用 call 方法来执行其他填充器(seeder)类。使用 call 方法可以将数据库填充拆分为多个文件,避免单个填充器类过于庞大。call 方法接收一个需要执行的填充器类数组:

/**
 * 运行数据库填充器。
 */
public function run(): void
{
    $this->call([
        UserSeeder::class,
        PostSeeder::class,
        CommentSeeder::class,
    ]);
}

静默模型事件

在运行填充器(seeds)时,你可能希望阻止模型触发事件。这可以通过使用 WithoutModelEvents 特性(trait)来实现。使用该特性后,即使通过 call 方法执行了其他填充器类,也不会触发任何模型事件:

<?php

namespace Database\Seeders;

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

class DatabaseSeeder extends Seeder
{
    use WithoutModelEvents;

    /**
     * 运行数据库填充器。
     */
    public function run(): void
    {
        $this->call([
            UserSeeder::class,
        ]);
    }
}

运行填充器

你可以使用 db:seed Artisan 命令来为数据库填充数据。默认情况下,db:seed 命令会运行 Database\Seeders\DatabaseSeeder 类,而该类又可以调用其他填充器类。不过,你也可以使用 --class 选项单独指定某个填充器类执行:

php artisan db:seed

php artisan db:seed --class=UserSeeder

你还可以结合 migrate:fresh 命令和 --seed 选项来填充数据库,这会先删除所有数据表,然后重新执行所有迁移操作,非常适合完整重建数据库。使用 --seeder 选项可以指定要运行的特定填充器:

php artisan migrate:fresh --seed

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

强制在生产环境运行填充器

有些填充操作可能会修改或丢失数据。为了保护你的生产数据库,在生产环境中运行填充命令时会要求确认。若要在生产环境中跳过确认直接执行填充器,可使用 --force 选项:

php artisan db:seed --force