我为在线学习平台提供了以下数据库结构:course
由modules
组成。 module
由lessons
和tasks
组成。每个元素都有用户特定的信息,每个模型都定义了相应的关系:
class Course extends Model {
public function user() {
return $this->belongsToMany(User::class)->withPivot('start_at', 'end_at');
}
public function modules() {
return $this->hasMany(Module::class);
}
// ...
}
class Module extends Model {
public function user() {
return $this->belongsToMany(User::class)->withPivot('start_at', 'end_at');
}
public function lessons() {
return $this->hasMany(Lesson::class);
}
public function tasks() {
return $this->hasMany(Lesson::class);
}
}
class Lesson extends Model {
public function user() {
return $this->belongsToMany(User::class)->withPivot('favourite', 'completed_at');
}
}
class Task extends Model {
public function user() {
return $this->belongsToMany(User::class)->withPivot('completed_at');
}
}
我的目标是在course
模型上加载包含以下范围的完整课程:
class Course extends Model {
// ...
public function scopeWithModules($query) {
return $query->with(['modules' => function ($q) {
$q->with(['user' => function ($q) { $q->where('user_id', auth()->user()->id); }])
->whereHas('user', function ($q) { $q->where('user_id', auth()->user()->id); });
}]);
}
public function scopeWithLessons($query) {
return $query->with(['modules.lessons' => function ($q) {
$q->with(['user' => function ($q) { $q->where('user_id', auth()->user()->id); }])
->whereHas('user', function ($q) { $q->where('user_id', auth()->user()->id); });
}]);
}
public function scopeWithTasks($query) {
return $query->with(['modules.tasks' => function ($q) {
$q->with(['user' => function ($q) { $q->where('user_id', auth()->user()->id); }])
->whereHas('user', function ($q) { $q->where('user_id', auth()->user()->id); });
}]);
}
// ...
}
仅这些范围中的每一个都能正常工作。但是组合它们将覆盖之前的那些,因此只会执行这些范围中的最后一个。
执行此
$course = Course::whereSlug('learning-abc')
->withModules()
->withLessons()
->withTasks()
->firstOrFail();
将为我提供有关模块和任务的课程(但没有课程和模块的用户信息)。
当然,我可以写一个像withModulesLessonsTasks()
这样的庞大范围,但我希望有一个更优雅的解决方案。有什么想法吗?
我之前:
$course = Course::whereSlug('learning-abc')
->with([
'modules.user',
'modules.lessons.user',
'modules.tasks.user'
])
->firstOrFail();
除了过滤auth()->user()
之外,工作正常。