【发布时间】:2015-06-24 05:16:03
【问题描述】:
我已经使用 Eloquent 构建了一个存储库层。我在表之间有很多复杂的关系,并且能够使用 eloquent 轻松构建所有查询,我非常依赖 WhereHas 查询来根据关系的条件进行查询。
在完成所有查询并开始工作后,最后要做的事情是在我的一些查询中添加一个选项,以包括 softDeleted 记录(在某个日期之后删除) - 这突出了一些问题。
例如,我可能有一个查询,它通过急切加载必要的数据开始如下:
public function query()
{
$this->query = AssetInstance::with('asset.type', 'zoneInstance.type', 'zoneInstance.zone');
)
然后我可能有一个函数来选择性地优化查询,如下所示:
function filterByZoneInstance($zone_instance_id)
{
$this->query->whereZoneInstanceId($zone_instance_id);
return $this;
}
我可能有另一个函数来进一步细化查询:
public function filterByZoneType($type)
{
$this->query->whereHas('zone_instance', function($q) use($type){
return $q->whereHas('type', function($q2){
return $q2->whereName($type);
});
});
}
public function get()
{
return $this->query->get();
}
所以这一切都很好,我可以这样做:
$this->query()->filterByZoneType('typex')->get();
现在,假设我想包含 softDeleteResults,我可以这样做:
public function includeTrashed()
{
$this->query->withTashed();
return $this;
}
但这并没有传递到关系,所以是的,所有assetInstances(包括软删除都会被拉入)但不是所有zoneInstances,如果关系(例如zone_instance已被软删除),这反过来会导致filterByZoneType失败.
所以我认为没问题 - 我可以用垃圾加载关系:
public function query()
{
$this->query = AssetInstance::with(['asset.type', 'ZoneInstance' => function ($q){
$q->withTrashed();
}, 'zoneInstance.type', 'zoneInstance.zone']);
)
这种方法一直有效,直到您应用 whereHas 查询,此时带有 Trashed 的 eagerloading 被 wherehas 查询覆盖,该查询执行它自己的急切加载(没有垃圾);
我尝试在 whereHas 闭包中应用约束,但它不起作用:
public function filterByZoneType($type)
{
$this->query->whereHas('zone_instance', function($q) use($type){
return $q->whereHas('type', function($q2){
return $q2->whereName($type)->withTrashed();
})->withTrashed();
});
}
我决定在这一点上使用原始查询,不幸的是,这有类似的效果,所以例如,如果我做这样的事情:
$this->query->whereRaw("asset_instances.`deleted_at` <= '2014-03-11 00:00:00' and (select count(*) from `variable_data_package_instances` where `variable_data_package_instances`.`asset_instance_id` = `asset_instances`.`id` and `variable_data_package_instances`.`deleted_at` <= '2014-03-11 00:00:00')");
我现在看到的是,废弃的 zoneInstances 不再急切加载(来自之前调用的 query() 函数)。
有没有人幸运地使用雄辩的关系查询来带来垃圾结果?
【问题讨论】:
标签: laravel eloquent laravel-5 soft-delete