在枢轴模型上对关系进行预加载
是否有办法在预加载中加载在中间模型中定义的关联,以避免N+1查询?
经过查阅文档和大量文章,我得到了以下4 个模型:
- Student
- Assessment
- StudentAssessment(M-N中间表)
- AssessmentResult(与StudentAssessment的一对一关系)
每个模型的关系:
- Student => assessments(): BelongsToMany
- Assessment => students(): BelongsToMany
- StudentAssessment => student(): BelongsTo, assessments(): BelongsTo, assessment_result(): HasOne
- AssessmentResult: student_assessment(): BelongsTo
StudentAssessment与 AssessmentResult都继承自Pivot而不是Model。students 关系在 Assessment 模型上也明确使用 withPivot 和 using:
public function students(): BelongsToMany
{
return $this->belongsToMany(
Student::class,
'student_assessments',
'assessment_id',
'student_id'
)->using(StudentAssessment::class)
->withPivot('id');
}
我仍然无法实现 $assessment->students()->with('pivot.assessment_result')。在预加载路径中,Laravel对中间表关系并不友好。
当然,我可以使用 foreach > load() 的模式逐个加载结果。只是我想避免那样做。
解决方案
你可以通过将pivot转换为自定义pivot模型来实现—
class StudentAssessment extends Pivot
{
protected $table = 'student_assessment';
public function assessment_result()
{
return $this->hasOne(AssessmentResult::class, 'student_assessment_id');
}
}
在Assessment模型上定义关系 -
class Assessment extends Model
{
public function students()
{
return $this->belongsToMany(Student::class)
->using(StudentAssessment::class)
->withPivot(['id']);
}
}
现在你可以在pivot模型上定义关系,这些关系在通过父关系对pivot模型进行水合后就可用 -
$assessments = Assessment::with('students')->get();
用法 -
foreach ($assessments as $assessment) {
foreach ($assessment->students as $student) {
$result = $student->pivot->assessment_result;
}
}
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。