Laravel 8+工厂需置于database/factories/下且类名匹配(如UserFactory),嵌套子目录将导致自动发现失败;Laravel 9+起应使用User::factory()->count(5)->create()而非factory(User::class);unique()仅在同一工厂实例内有效,批量创建才保证唯一性;测试中需手动清理关联表或配置级联删除。
工厂类没被自动发现,
里调用
报错
Laravel 8+ 默认启用模型工厂自动发现,但前提是工厂文件得放在
下,且类名要严格匹配模型名(如
对应
)。如果工厂类在子目录(比如
),Laravel 就找不到它。
检查路径:必须是
,不能嵌套子文件夹
确认命名空间:Laravel 10 推荐用
显式引入,而不是依赖自动发现
手动注册(临时救急):在
的
方法里加
创建的数据没进数据库,或只插了 1 条
常见于 Laravel 9+,因为
辅助函数已被弃用,直接调用会触发 E_USER_DEPRECATED 警告,且在某些配置下实际执行的是空操作——尤其当你混用了旧写法和新工厂类时。
改用模型静态方法:
,这是当前唯一可靠方式
别再用
,它在 Laravel 9.2+ 已失效
如果用了
,注意它返回的是集合而非模型实例数组,字段验证失败时不会抛异常,而是静默跳过
工厂里用
还是报
的
是懒加载的,只对同一工厂实例内连续调用有效。一旦你分多次调用
(比如循环中),每次都是新实例,
不跨实例记忆。
批量创建时才安全:
,这时
能覆盖全部 10 次生成
单条创建需手动去重:用
或先查后插,例如
更稳的做法:在工厂里用
,避开唯一性校验逻辑
测试中用工厂造数据,但
迁移后关联表数据还在
工厂本身不负责清理,它只管插入。如果你在测试里用
,迁移回滚时只会清空
表,
表里的记录还在,下次测试可能因外键约束失败。
确保迁移文件里定义了
并启用
不要依赖工厂自动清理,测试前显式清空:
(慎用,注意顺序)
更推荐方案:在
的
里用
,比 truncate 更安全,不重置自增 ID
工厂最麻烦的不是写法,是它和迁移、数据库状态、Faker 实例生命周期这三者的耦合——稍不注意,测试就变成“看运气跑通”。尤其在并行运行测试或使用内存数据库时,
和事务隔离级别会联合给你埋雷。
php artisan tinkerApp\Models\User::factory()->create()database/factoriesUserFactoryUserdatabase/factories/User/UserFactory.phpdatabase/factories/xxxFactory.phpuse Database\Factories\UserFactory;DatabaseFactoryconfigure()$this->factories([UserFactory::class]);factory()->count(5)->create()factory()User::factory()->count(5)->create()factory(User::class)->count(5)->create()createMany()$this->faker->unique()->emailIntegrity constraint violation: 1062 Duplicate entryFakerunique()User::factory()->create()unique()User::factory()->count(10)->create()unique()retry()do { $email = $this->faker->email; } while (User::where('email', $email)->exists());$this->faker->uuid . '@example.com'refreshDatabaseUser::factory()->has(Post::factory()->count(3))->create()userspostsforeignIdonDelete('cascade')Post::truncate();TestCasesetUp()DB::table('posts')->delete();unique()