默认生成在database/factories目录,Laravel 8+需手动注册或use引入;工厂类命名须匹配模型(如UserFactory对应User),Laravel 9+须继承Illuminate\Database\Eloquent\Factories\Factory;create()写入数据库并触发事件,make()仅构造内存对象且$exists为false;sequence()按调用顺序轮换值,state()优先级高于sequence()。

php artisan make:factory 生成的文件在哪
默认放在 database/factories 目录下,Laravel 8+ 之后不再自动注册工厂类,必须手动在 DatabaseFactory 中定义或使用 use Database\Factories\UserFactory; 显式引入。
常见错误现象:Call to undefined method App\Models\User::factory()——不是模型没写 factory 方法,而是工厂类没被发现或没关联上。
- 确认工厂类命名是否匹配模型名(如
UserFactory对应User) - Laravel 9+ 要求工厂类继承
\Illuminate\Database\Eloquent\Factories\Factory,别用老版本的Factory基类 - 如果用了自定义命名空间(比如
App\Factories),得在模型里重写newFactory()方法返回对应类
factory()->create() 和 factory()->make() 的区别
create() 写入数据库,make() 只构造内存对象不持久化——这是最常混淆的点,尤其在测试中误用 create() 导致事务污染或主键冲突。
使用场景举例:想测表单验证逻辑,用 make() 更快更干净;要测关联查询或真实 DB 行为,才用 create()。
-
create()会触发模型的creating/created事件,make()不会 -
make()返回的是模型实例,但$model->exists === false,很多判断逻辑依赖这个属性 - 批量生成时,
factory(User::class)->count(10)->make()返回集合,create()才真正插入 10 条
工厂里用 sequence() 控制字段递增或轮换
需要模拟不同状态、编号、类型的数据时,硬写数组或随机容易失控,sequence() 是最轻量又可控的方式。
比如用户角色字段只有 'admin' / 'user' / 'guest' 三种,不想靠 fake()->randomElement() 碰运气:
return [
'name' => $this->faker->name,
'role' => $this->sequence('admin', 'user', 'guest'),
];
性能影响几乎为零,但要注意:sequence() 是按调用顺序轮换的,不是按模型实例顺序——如果并发跑测试,结果可能不一致;单进程测试没问题。
-
sequence()返回的是闭包,不能直接 echo 或 log,调试时得先调用() - 和
state()混用时,state()优先级更高,会覆盖sequence()的值 - 不要在
for()循环里重复 new 工厂类,sequence()的计数器是实例级的
测试中 factory() 报错 Class "UserFactory" not found
根本原因不是文件不存在,而是自动加载没生效,或者工厂类没按 PSR-4 规则命名/放置。
Laravel 不再扫描 database/factories 下的所有类,只认你显式 use 或注册的。
- 检查工厂类的命名空间是否为空(Laravel 默认期望无命名空间),有就删掉
namespace行 - 运行
composer dump-autoload,特别是改过文件位置或命名后 - 如果工厂类在子目录(如
database/factories/User/UserFactory.php),必须在模型里指定:protected static function newFactory() { return \Database\Factories\User\UserFactory::new(); }
复杂点在于:工厂类可以分散在多个路径,但 Laravel 只通过模型上的 newFactory() 或默认命名规则找一个,不会合并或 fallback。漏配一个,就报这个错。









