Laravel 中 Factory 与 Seeder 有什么区别
Laravel 的 Factory 负责按模型批量生成假数据(借助 Faker),Seeder 负责编排数据填充流程。Seeder 管"填什么、按什么顺序",Factory 管"每条数据长什么样",两者常配合使用。
直接回答:Factory 是数据生成器——定义某个模型的假数据模板并可批量造数;Seeder 是填充脚本——决定向数据库写入哪些数据、以什么顺序执行。 实际开发中通常在 Seeder 里调用 Factory:Seeder 编排流程,Factory 产出数据。
Factory:定义"数据长什么样"
以下是已有 Laravel 项目中的类体片段,省略 namespace/import;需补齐 Factory、Seeder、DB、User 的实际命名空间,模型还需 HasFactory 和示例关联。固定测试密码与 Faker 数据仅限隔离测试数据库。
Factory 绑定一个模型,用 Faker 生成随机但格式合理的字段值:
// database/factories/UserFactory.php
class UserFactory extends Factory
{
public function definition(): array
{
return [
'name' => fake()->name(),
'email' => fake()->unique()->safeEmail(),
'password' => bcrypt('password'),
];
}
}
使用:
User::factory()->count(50)->create(); // 造 50 个用户
User::factory()->hasPosts(3)->create(); // 顺便给每个用户造 3 篇文章(关联关系)
User::factory()->make(); // 只生成模型实例,不落库(常用于单测)
Factory 的强项:
- 批量生成:一条命令造任意数量
- 处理关联:
hasPosts()、for(User::factory())等轻松构造关联数据 - 状态变换:
->state(['role' => 'admin'])快速得到特定形态的数据 - 测试中复用:单元测试里
->make()不落库,又快又干净
Seeder:定义"怎么填"
Seeder 类放在 database/seeders/,入口是 DatabaseSeeder,通过 call() 编排执行顺序:
class DatabaseSeeder extends Seeder
{
public function run(): void
{
// 直接写死基础数据
DB::table('roles')->insert([
['name' => 'admin'],
['name' => 'user'],
]);
// 调用 Factory 造测试数据
User::factory()->count(50)->hasPosts(1)->create();
// 编排其他 Seeder
$this->call([
ProductSeeder::class,
OrderSeeder::class,
]);
}
}
执行:
php artisan db:seed # 跑 DatabaseSeeder
php artisan db:seed --class=ProductSeeder
# 破坏性命令:删除目标连接全部数据表,仅限已确认可丢弃的测试数据库
php artisan migrate:fresh --seed
分工对照
| 维度 | Factory | Seeder |
|---|---|---|
| 职责 | 定义单模型假数据模板 | 编排整体填充流程 |
| 随机数据 | 内置 Faker,天生支持 | 本身不管随机,可调用 Factory |
| 关联数据 | 一行代码带出关联 | 需借助 Factory 或手写 |
| 典型场景 | 开发环境造量、单元测试 | 初始化基础数据(角色、字典表)、演示数据 |
| 执行方式 | 被调用,不单独运行 | php artisan db:seed 直接运行 |
一句话:初始化"必须有"的数据用 Seeder 手写,造"看着像真的"的大量数据用 Factory,两者在 DatabaseSeeder 里会师。
常见问题(FAQ)
Q:生产环境能跑 Seeder 吗?
A:可以但要谨慎——幂等初始化字典表可使用受审查 Seeder;创建管理员应走受控身份流程,不使用示例固定密码;测试假数据绝不该进生产。可用 --class 限定范围,检查连接、备份与回退,代码环境限制不能替代数据库权限隔离。
Q:Factory 生成的中文数据怎么弄?
A:在 config/app.php 或 AppServiceProvider 中把 Faker locale 设为 zh_CN,Faker 就会产出中文姓名、地址等本地化假数据。
Q:老项目的 factory(App\User::class, 50) 写法报错?
A:那是 Laravel 7 及之前的全局函数式写法。8+ 改为类式 Factory:模型加 HasFactory trait,用 User::factory()->count(50)->create()。升级时需逐个迁移。
参考资料
本文依据官方资料核对,未进行现场运行测试;代码与配置示例需结合实际版本、权限和环境验证。