Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/laravel/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
雄辩(Laravel 5)-如何在关系查询中包括软删除记录(whereHas)?_Laravel_Eloquent_Laravel 5_Soft Delete - Fatal编程技术网

雄辩(Laravel 5)-如何在关系查询中包括软删除记录(whereHas)?

雄辩(Laravel 5)-如何在关系查询中包括软删除记录(whereHas)?,laravel,eloquent,laravel-5,soft-delete,Laravel,Eloquent,Laravel 5,Soft Delete,我已经使用Eloquent构建了一个存储库层。我在表之间有很多复杂的关系,并且能够使用eloquent轻松地构造所有查询,我非常依赖WhereHas查询来根据关系上的条件进行查询 完成所有查询并运行后,最后要做的事情是在我的一些查询中加入软删除记录(在某个日期后删除)——这突出了几个问题 因此,例如,我可能有一个查询,它通过加载必要的数据如下所示开始: public function query() { $this->query = AssetInstance::with('ass

我已经使用Eloquent构建了一个存储库层。我在表之间有很多复杂的关系,并且能够使用eloquent轻松地构造所有查询,我非常依赖WhereHas查询来根据关系上的条件进行查询

完成所有查询并运行后,最后要做的事情是在我的一些查询中加入软删除记录(在某个日期后删除)——这突出了几个问题

因此,例如,我可能有一个查询,它通过加载必要的数据如下所示开始:

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;
}
但这不会传递到关系,因此,是的,所有AssetInstance(包括软删除)都会被拉入,但并非所有ZoneInstance都会被拉入,如果关系(例如zone_实例已被软删除),这反过来会导致filterByZoneType失败

所以我觉得没问题-我可以用垃圾来加载关系:

public function query()
    {
        $this->query = AssetInstance::with(['asset.type', 'ZoneInstance' => function ($q){
                $q->withTrashed();
            }, 'zoneInstance.type', 'zoneInstance.zone']);
    )
在应用whereHas查询之前,这种方法一直有效,在这一点上,whereHas查询执行其自身的急切加载(无垃圾),而急切加载withTrashed被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')");
$this->query->whereRaw(“资产”实例.`deleted\u at`这是怎么回事:

public function query()
    {
        $this->query = AssetInstance::with(['asset.type', 'ZoneInstance' => function ($q){
                $q->withTrashed()->with('type','zone');
            }]);
    )->get();
}
那么这个呢:

public function query()
    {
        $this->query = AssetInstance::with(['asset.type', 'ZoneInstance' => function ($q){
                $q->withTrashed()->with('type','zone');
            }]);
    )->get();
}

我注意到以下代码也存在同样的问题:

class Reward extends Model 
{
    /* ... */

    public function membership()
    {
        return $this->belongsTo(Membership::class);
    }

    /* ... */
}

当我想获得与已删除会员资格相关联的奖励时,我使用以下查询:

Reward::whereHas( ['membership' => function($query){
    $query->withTrashed() ;
}] )->get();
但是,它不起作用,因为“withTrashed”方法不是作用域(添加约束),而是创建一个新查询:

public static function withTrashed()
{
    return (new static)->newQueryWithoutScope(new SoftDeletingScope);
}
因此,目前我找到的唯一解决方案是使用另一个关系:

class Reward extends Model 
{
    /* ... */

    public function membershipWithTrashed()
    {
        return $this->belongsTo(Membership::class)->withTrashed();
    }

    /* ... */
}
然后:

Reward::has( 'membershipWithTrashed' )->get();
工作


在我看来,这是一个相当丑陋的解决方案,需要修复SoftDelete特性。

我注意到以下代码也存在同样的问题:

class Reward extends Model 
{
    /* ... */

    public function membership()
    {
        return $this->belongsTo(Membership::class);
    }

    /* ... */
}

当我想获得与已删除会员资格相关联的奖励时,我使用以下查询:

Reward::whereHas( ['membership' => function($query){
    $query->withTrashed() ;
}] )->get();
但是,它不起作用,因为“withTrashed”方法不是作用域(添加约束),而是创建一个新查询:

public static function withTrashed()
{
    return (new static)->newQueryWithoutScope(new SoftDeletingScope);
}
因此,目前我找到的唯一解决方案是使用另一个关系:

class Reward extends Model 
{
    /* ... */

    public function membershipWithTrashed()
    {
        return $this->belongsTo(Membership::class)->withTrashed();
    }

    /* ... */
}
然后:

Reward::has( 'membershipWithTrashed' )->get();
工作


在我看来,这是一个相当丑陋的解决方案,需要修复SoftDelete特性。

Laravel 5.2已经修复了这个问题。不再需要丑陋的黑客


请参阅:

Laravel 5.2已修复此问题。不再需要丑陋的黑客


请参阅:

我不再经常使用Laravel/PHP,因此没有花时间确认这是正确的。但是,问题似乎很相似,因此我相信您是正确的。因为当时没有任何其他答案有帮助,我将此标记为已被接受,因为它似乎对任何登陆此处的人都是最有帮助的答案。如果有人对此有异议,请评论更正。感谢您接受答案。过去几天我自己也遇到了这个问题,很难发现Laravel已经解决了它。希望这个答案能帮助其他人节省时间。我不再经常使用Laravel/PHP,因此没有花时间确认是否正确我认为这是固定的。但是,这些问题看起来很相似,所以我相信你是正确的。因为当时没有任何其他答案对我有帮助,所以我将此标记为已接受,因为它似乎对任何登陆这里的人都是最有帮助的答案。如果有人质疑这是固定的,请评论更正。感谢你接受答案。我很高兴在过去的几天里,我自己也遇到了这个问题,很难发现拉威尔已经解决了这个问题。希望这个答案能帮助其他人节省时间。