Laravel Eloquent:排除带有测验或竞赛的标题,同时包含带有练习的标题

问题描述 投票:0回答:1

我正在开发 Laravel 应用程序,我需要根据标题与练习、测验和竞赛的关系来过滤标题。具体来说,我想检索具有相关实践但没有任何相关测验或竞赛的标题。但是,我遇到了一个问题,即同时具有练习和测验(或竞赛)的标题被排除在结果集中。

这是我的代码的简化版本:

public function index(Request $request): JsonResponse
{
    $user = User::find(auth()->id());
    
    // ... other request handling code

    $titlesQuery = Title::with(['practices', 'quizzes', 'contests']);

    if (!$user->is_accepted) {
        $titlesQuery->whereHas('practices')
                     ->whereDoesntHave('quizzes')
                     ->whereDoesntHave('contests');
    }

    // Additional filters and search terms

    return $titlesQuery->paginate($limit);
}

问题:
我面临的问题是,当我运行此查询时,任何包含测验的标题(即使它也有练习)都被完全排除在结果之外。我只想排除没有任何练习的带有测验或竞赛的标题,并仅在必要时返回练习。

示例场景 例如,如果我有以下记录:

标题 A 既有练习又有测验。
Title B 只有一个练习。
标题 C 有一个测验。
Title C 有一场比赛。

我希望返回我的查询:

标题 A(应返回练习并排除测验)
标题 B(应包含在内)
标题 C(不应包含在内,因为它是测验)
Title D(不应包含在内,因为这是一场竞赛)

其他信息

我的标题模型具有通过练习、测验和竞赛定义的关系。 我想维护稍后在查询中应用的其他过滤器(例如搜索、类别和子类别)。

我的模特关系:

//Title:
 public function quizzes()
    {
        return $this->hasMany(Quiz::class);
    }

    public function practices()
    {
        return $this->hasMany(Practice::class);
    }

    public function contests()
    {
        return $this->hasMany(Contest::class);
    }
//Quiz, Practice, Contest
    public function title()
    {
        return $this->belongsTo(Title::class);
    }

我尝试过的事情 我尝试重组我的查询,首先使用 whereHas 进行练习,然后使用 whereDoesntHave 进行测验和竞赛,但它仍然排除有测验的标题,而我只想在它们没有练习时排除它们。

我还尝试运行子查询,例如:

$titlesQuery->whereHas('practices')
    ->where(function ($query) {
        // Exclude titles that have quizzes or contests
        $query->whereDoesntHave('quizzes')
              ->whereDoesntHave('contests');
         });

任何有关如何实现这一目标的指导将不胜感激!

php laravel eloquent relationship query-builder
1个回答
0
投票

你应该使用子查询,但不是你写的方式,试试这个方法:

        $titlesQuery->whereHas('practices',function($q){
            $q->whereDoesntHave('quizzes')
              ->whereDoesntHave('contests');
        });
© www.soinside.com 2019 - 2024. All rights reserved.