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);
}
然后使用 doesntHave
和 ordoesntHave
构建查询。
$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');
我有一个模型 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);
}
然后使用 doesntHave
和 ordoesntHave
构建查询。
$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');