Laravel 8+工厂类必须置于database/factories/下、类名严格匹配ModelNameFactory.php、protected $model = App\Models\User::class不可省略,否则User::factory()报错;须用fake()->name()而非$this->faker->name,且unique()仅在同实例内有效。

工厂类必须放在 database/factories/ 目录下,类名严格匹配模型名 + Factory 后缀(如 User 对应 UserFactory),否则 User::factory() 会直接报 Unable to locate factory for [App\Models\User]。
工厂文件怎么生成和放对位置
用 php artisan make:factory UserFactory --model=User 生成后,检查三件事:
- 文件路径是
database/factories/UserFactory.php—— 不能有子目录(比如database/factories/User/UserFactory.php就找不到) - 类名是
UserFactory,且继承自Illuminate\Database\Eloquent\Factories\Factory -
protected $model = User::class;这行必须存在,Laravel 不靠文件名推断模型,只认这个属性
definition() 里怎么写字段值
字段数组里不能直接写 $this->faker->name(旧写法残留),新版要改用 fake()->name() 或显式注入 Faker\Generator:
- 推荐写法:
'name' => fake()->name(), 'email' => fake()->unique()->safeEmail() - 如果需要更复杂逻辑(比如根据状态动态设
slug),可在definition()里调用fake()+ 手动计算,但别在闭包里再嵌套fake()调用——它不是线程安全的 -
fake()->unique()只对同一工厂实例内连续调用有效;User::factory()->count(10)->create()是安全的,但循环里写 10 次User::factory()->create()会重复邮箱
模型类要不要加 HasFactory trait
不是必须,但加了才能用 User::factory() 静态方法;不加的话,得手动指定工厂类:
- 加了 trait:
User::factory()->create()(自动找UserFactory) - 没加 trait:得写
(new UserFactory())->create()或UserFactory::new()->create(),麻烦且易错 - trait 里还有
newFactory()方法,可用于切换不同工厂实现(比如测试时用 MockFactory),但日常开发基本用不到
为什么 factory(User::class)->create() 突然不工作了
这是 Laravel 8+ 的硬性变更,不是 bug:
-
factory()全局辅助函数在 Laravel 9.2+ 已被完全移除,调用会静默失败或触发 deprecated 警告 - 所有代码必须迁移到模型静态方法:
User::factory()->create()、Post::factory()->count(3)->create() - 如果你混用了旧工厂文件(Laravel 7 风格)和新框架,装
laravel/legacy-factories包能兼容,但只是过渡方案,不解决根本问题
最常被忽略的一点:工厂类里的 protected $model 必须是完整命名空间路径(如 App\Models\User::class),哪怕模型在默认命名空间下也不能省略 App\Models\ —— Laravel 的自动发现机制依赖这个字符串做精确匹配,写错一个字母就找不到。


















