在hasManyThrough关系的中间模型上withwithTrashed

时间:2019-03-01 09:29:50

标签: laravel eloquent laravel-5.5

我有3个与此相关的类:

Exhibitor
'- Bills
   '- Tickets

票据和票证都使用SoftDeletes特性,在Exhibitor类上,我有这种关系:

public function tickets()
{
    return $this->hasManyThrough(Ticket::class, Bill::class);
}

我需要获取所有票证,包括已删除的票证(withTrashed),但这还需要包括所有已删除的帐单。问题是,withTrashed仅适用于票证模型,而不适用于账单。

此查询

    $tickets = exhibitor()->tickets()->withTrashed()
        ->where('bills.updated_at', '>=', Carbon::parse($since))
        ->orderBy('tickets.id')
        ->get();

生成此SQL

select `tickets`.*, `bills`.`exhibitor_id` from `tickets`
inner join `bills` on `bills`.`id` = `tickets`.`bill_id`
where `bills`.`deleted_at` is null 
and `bills`.`exhibitor_id` = ?
and `bills`.`updated_at` >= ?
order by `tickets`.`id` asc

我应该使用不带“ billsdeleted_at为空”的SQL,如下所示:

select `tickets`.*, `bills`.`exhibitor_id` from `tickets`
inner join `bills` on `bills`.`id` = `tickets`.`bill_id`
where `bills`.`exhibitor_id` = ?
and `bills`.`updated_at` >= ?
order by `tickets`.`id` asc

但是我看不到可以为Bill模型设置withTrashed()的任何选项。我认为应该可以在hasManyThrough方法上设置回调查询,但是根据API,对此不提供任何支持。这似乎很简单,我感觉自己正在忽略某些东西,但我找不到它...

2 个答案:

答案 0 :(得分:2)

目前无法实现:https://github.com/laravel/framework/issues/23039

如果您不介意安装外部软件包,则可以使用我创建的该软件包: https://github.com/staudenmeir/eloquent-has-many-deep

class Exhibitor extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function tickets()
    {
        return $this->hasManyDeep(Ticket::class, [Bill::class])
            ->withTrashed('bills.deleted_at');
    }
}

答案 1 :(得分:0)

由于查询变得有点复杂,因此我将在票证模型上定义范围。

public function scopeBillsSince($query, $since)
    return $query->whereHas('bills', function ($query2) use ($since) {
        return $query2->withThrashed()->where('updated_at', '>=', Carbon::parse($since))
    });
}

现在使用该范围,您可以像下面这样查询票证:

$tickets = exhibitor()->tickets()->withTrashed()->billsSince($since);