Eloquent: 检查关系是否有特定条件

Eloquent: check if relationship has certain conditions

我有一个模型 Survey 与另一个模型 hasOne 相关,另一个模型 Installation 与另一个模型 hasMany 相关 Assignment。 所以我定义了一个 hasManyThrough 这样的关系

public function assignments()
    {
        return $this->hasManyThrough(Assignment::class,Installation::class);
    }

我想编写一个查询来获取任何 Survey,其中与调查关联的 Assignments 没有 assignment.type 0、1、2、3 和 4。

即 每个调查应该有 5 个作业和记录

Survey => [
[Assignment => [type = 0]]
[Assignment => [type = 1]]
[Assignment => [type = 2]]
[Assignment => [type = 3]]
[Assignment => [type = 4]]
]

我试过这个查询

 $schedulables = Survey::whereNotNull('installer_id')
            ->where(function ($query) {
                $query
                    ->whereNotExists(function ($query) {
                        return $query->raw('SELECT * FROM assignments,installations where assignments.installation_id = installations.id and installations.survey_id = surveys.id and assignments.type= 1');
                    })
                    ->orwhereNotExists(function ($query) {
                        return $query->raw('SELECT * FROM assignments,installations where assignments.installation_id = installations.id and installations.survey_id = surveys.id and assignments.type= 2');
                    })
                    ->orwhereNotExists(function ($query) {
                        return $query->raw('SELECT * FROM assignments,installations where assignments.installation_id = installations.id and installations.survey_id = surveys.id and assignments.type= 3');
                    })
                    ->orwhereNotExists(function ($query) {
                        return $query->raw('SELECT * FROM assignments,installations where assignments.installation_id = installations.id and installations.survey_id = surveys.id and assignments.type= 4');
                    });

            })
            ->with('customer', 'installer', 'installation')
            ->latest('updated_at')->get();

如有任何建议和帮助,我们将不胜感激。

如果我没有正确理解你的问题,你可以使用 whereHas() and whereNotIn() 来实现你想要的:

$schedulables = Survey
    ::with('customer', 'installer', 'installation')
    ->whereNotNull('installer_id')
    ->whereHas('assignments', function ($query) {
        $query->whereNotIn('type', [0, 1, 2, 3, 4]);
    })
    ->latest('updated_at')
    ->get();

我的最终解决方案是在 Survey 模型中创建这些关系

 public function assignment_outdoor(){
        return $this->hasManyThrough(Assignment::class,Installation::class)
            ->where('assignments.type',1)
            ->where('assignments.status',2);
    }
    public function assignment_indoor(){
        return $this->hasManyThrough(Assignment::class,Installation::class)
            ->where('assignments.type',2)
            ->where('assignments.status',2);
    }
    public function assignment_testing_activation(){
        return $this->hasManyThrough(Assignment::class,Installation::class)
            ->where('assignments.type',3)
            ->where('assignments.status',2);
    }
    public function assignment_lm_splicing(){
        return $this->hasManyThrough(Assignment::class,Installation::class)
            ->where('assignments.type',4)
            ->where('assignments.status',2);
    }

然后使用 doesntHaveordoesntHave 构建查询。

$schedulables = Survey::when($installer_filter, function ($query, $installer_filter) {
            return $query->where('installer_id', $installer_filter);
        })
            ->whereNotNull('installer_id')
//actual solution
            ->where(function ($query) {
                return $query

                    ->doesntHave('assignment_outdoor')
                    ->orDoesntHave('assignment_indoor')
                    ->orDoesntHave('assignment_testing_activation')
                    ->orDoesntHave('assignment_lm_splicing');

            })
//end
            ->doesntHave('network_job_order_customer')
            ->with('customer', 'installer', 'installation')
            ->latest('updated_at');