Laravel:在嵌套关系上组合多个查询范围,而不会覆盖以前的关系

时间:2017-11-28 13:09:11

标签: laravel eloquent relationships scopes

我为在线学习平台提供了以下数据库结构:coursemodules组成。 modulelessonstasks组成。每个元素都有用户特定的信息,每个模型都定义了相应的关系:

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()之外,工作正常。

0 个答案:

没有答案