如何用Laravel Factory创建各带独立Company的10个Service模型
问题:Laravel工厂创建关联模型时重复使用同一父模型且关联加载为空
需求
创建10个Service模型实例,每个实例对应唯一的Company模型(Service与Company为belongsTo关联)。
当前代码与问题
Service模型关联定义
/** * Get the company a specified service belongs to * * @return BelongsTo */ public function company(): BelongsTo { return $this->belongsTo(Company::class); }
测试代码
Service::factory() ->count(10) ->create([ 'company_id' => Company::factory()->create(), ]); print_r((Company::all())->toArray()); print_r((Service::with(['company'])->get())->toArray());
测试结果
- 成功生成10个
Service,但所有Service的company_id完全相同,仅生成1个Company - 加载
company关联时,所有Service的company字段为空
问题原因
- 重复使用同一Company:直接传入
Company::factory()->create()时,该代码仅执行一次,生成的ID被复用给所有10个Service。 - 关联加载为空:使用字符串类型主键时,若未在模型中明确声明主键类型,Eloquent会默认按整数处理主键,导致关联查询不匹配。
解决方案
方案1:使用闭包为每个Service生成独立Company
通过闭包让每个Service创建时都生成新的Company:
Service::factory() ->count(10) ->create(function () { return [ 'company_id' => Company::factory()->create()->id, ]; });
方案2:使用Laravel工厂的for方法(推荐)
利用Laravel工厂的关联语法,更简洁地创建一对一关联的模型:
Service::factory() ->count(10) ->for(Company::factory()) // 自动为每个Service创建并关联唯一Company ->create();
修复关联加载为空的问题
在Company模型中添加字符串主键声明:
class Company extends Model { use SoftDeletes; protected $keyType = 'string'; public $incrementing = false; // ... 其他模型代码 }
若Service模型主键也是字符串类型,同样需要添加上述配置。
验证结果
执行修复后的代码后,会生成10个Company和10个一一对应的Service,且Service::with('company')->get()能正常加载关联的Company数据。
内容的提问来源于stack exchange,提问作者BobbyP
相关产品推荐
相关产品推荐

