Laravel 8+工厂需置于database/factories/下且类名匹配(如UserFactory),嵌套子目录将导致自动发现失败;Laravel 9+起应使用User::factory()->count(5)->create()而非factory(User::class);unique()仅在同一工厂实例内有效,批量创建才保证唯一性;测试中需手动清理关联表或配置级联删除。

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


















