应优先使用 Post::factory(),它自动绑定模型并触发默认行为;Factory::new() 是裸构造器,易致字段为空或外键缺失,且 Laravel 10+ 已移除全局 factory() 辅助函数。
直接用 Post::factory(),99% 场景下别碰 Factory::new()。Laravel 10+ 已移除全局 factory() 辅助函数,Post::factory() 是标准入口——它自动绑定模型、加载 HasFactory trait、触发默认行为;而 Factory::new() 是裸工厂构造器,不关联模型,也不读取工厂类定义,容易导致字段为空或外键缺失。
常见错误:Call to undefined function factory() 不是路径错,是 Laravel 10 移除了该函数。修复只需把旧写法 factory(Post::class)->create() 全部替换成 Post::factory()->create()。
use IlluminateDatabaseEloquentFactoriesHasFactory
User 模型 → UserFactory 类,文件放在 database/factories/ 下IlluminateDatabaseEloquentFactoriesFactory,不能沿用 Laravel 7 之前的闭包式定义$this->faker->unique()->safeEmail() 在单次 create() 或 make() 中有效,但若在循环里反复调用 User::factory()->create(),Faker 的唯一计数器不会跨调用保留,最终触发 Integrity constraint violation。
正确做法是**一次性批量创建**:User::factory()->count(1000)->create()。此时 Faker 内部为本次批次维护独立去重池,所有邮箱互不重复。
如果内存受限必须分批(比如 200 条/批),别依赖 unique(),改用带随机后缀的构造方式:
$this->faker->numerify('user###@test.com')$this->faker->uuid() . '@test.com'注意:数据库字段加 UNIQUE 约束不是备选方案,而是必须项——它能提前暴露工厂逻辑缺陷,而不是等测试跑崩了才发现。
典型报错:SQLSTATE[HY000]: General error: 1364 Field 'user_id' doesn't have a default value,说明子模型(如 Post)没拿到父模型 ID。
根本原因常是工厂类未正确定义 $model 属性,或 PSR-4 自动加载路径错位,导致 Laravel 找不到对应工厂,回退到空工厂实例(所有字段为 null)。
关键规则:
Post::factory()->for($user)->create() 要求 $user 是已保存的模型实例(即 create() 返回的对象),不能是 make() 出来的临时对象User::factory()->has(Post::factory()->count(3))->create() 会自动生成用户 + 关联文章,并正确设置 post.user_id
protected $model = User::class;(Laravel 8+ 可省略,但低版本或自定义路径时仍需显式声明)别用 ->create(['name' => 'UK']),这会让全部记录都变成 UK;也别手写 20 次 create(),太冗余。
用 Sequence 类,按创建顺序动态返回不同属性数组:
use IlluminateDatabaseEloquentFactoriesSequence;$countries = Country::factory() ->count(20) ->sequence( ['name' => 'UK'], ['name' => 'USA'], fn () => ['name' => fake()->country()] ) ->create();
它会严格按顺序分配:第 1 条 name=UK,第 2 条 name=USA,剩下 18 条用 Faker 随机国家名。多个闭包写法更灵活,比如 fn ($index) => $index === 0 ? ['name' => 'UK'] : [],适合需要条件判断的场景。
容易被忽略的是:Sequence 只作用于当前 create() 调用批次,跨批次不共享状态;且必须确保工厂类的 definition() 方法不与 Sequence 冲突(比如 definition 里也写了 'name' 字段,会被覆盖)。