如何暂时关闭laravel垃圾过滤器?

时间:2018-09-27 10:22:23

标签: laravel laravel-5 soft-delete

说我有一个A,它的一个B和一个C的一个D。我想从A转到D,但是任何一个(或全部)对象可能已被删除。所以我必须这样做:

$d = $a->b()->withTrashed()->first()->c()->withTrashed()->first()->d()->withTrashed()->first()

这太可怕了。我真的很愿意这样做:

turnOffTrashedFilter();
$d = $a->b->c->d;

laravel有这种能力吗?

请注意,这只是一个例子-提示此问题的情况实际上要复杂得多,各种调用嵌套在其他调用中,因此实际上无法如上所述使用withTrashed。我需要在请求期间关闭过滤器,而不必修改大量代码以合并两个并行路径。

2 个答案:

答案 0 :(得分:1)

没有内置功能,但是可以做到

没有内置的方法来禁用自动软删除过滤。但是,这是可能的。软删除过滤器是全局作用域,已添加到类的启动方法中。可以这样删除它:

    \Event::listen('eloquent.booted:*', function($name) {
    $name = substr($name, 17); // event name is "eloquent.booted: some/class"
    $class = new \ReflectionClass($name);
    $prop = $class->getProperty('globalScopes');
    $prop->setAccessible(true);
    $scopes = $prop->getValue();
    foreach ($scopes as $c => &$s) {
        unset($s['Illuminate\Database\Eloquent\SoftDeletingScope']);
    }
    $prop->setValue($scopes);
});

这与启动事件挂钩,该事件在将全局范围添加到类之后立即触发。然后,它打开(私有静态)属性globalScopes,该属性是附加的全局范围的列表,并删除软删除的范围。这将防止softdelete范围附加到任何模型,只要它们的静态启动方法在添加事件侦听器之后称为

答案 1 :(得分:0)

相反,您可以在关系中使用withTrashed():

public function aTrashed()
{
    return $this->hasOne(A::class)->withTrashed();
}

public function bTrashed()
{
    return $this->hasMany(B::class)->withTrashed();
}

public function cTrashed()
{
    return $this->belongsToMany(C:class)->withTrashed();
}

// Then use it
$d = $z->aTrashed->bTrashed->cTrashed;