【问题标题】:withTrashed on the intermediate model of a hasManyThrough relationwithTrashed 在 hasManyThrough 关系的中间模型上
【发布时间】:2019-03-01 17:47:20
【问题描述】:

我有 3 个类似这样的类:

Exhibitor
'- Bills
   '- Tickets

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

而我应该需要这个没有“bills.deleted_at is null”的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,不支持此功能。这看起来很简单,我感觉我忽略了一些东西,但我找不到它......

【问题讨论】:

    标签: laravel eloquent laravel-5.5


    【解决方案1】:

    目前不可能: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');
        }
    }
    

    【讨论】:

    • 这个包其实很完美。它还解决了我在需要 3 级嵌套关系时遇到的另一个问题。谢谢乔纳斯。我最终在 Exhibitor 类上创建了第二个关系: public function TicketsWithTrashed() { return $this->hasManyDeep(Ticket::class, [Bill::class])->withTrashed(['bills.deleted_at'])- >withTrashed(); }
    【解决方案2】:

    我会在门票模型上定义一个范围,因为查询变得有点复杂。

    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);
    

    【讨论】:

    • 据我所知,范围查询进一步建立在exhibitor()->tickets()->withTrashed() 之上,并且已经丢失了已删除的账单,所以我不确定这有什么帮助,但我会试一试只是为了找出答案。
    • 刚刚证实了我的怀疑,你不能修改范围之前已经定义的查询。
    猜你喜欢
    • 2017-11-12
    • 1970-01-01
    • 2018-04-15
    • 1970-01-01
    • 1970-01-01
    • 2018-07-24
    • 2014-11-10
    • 2016-02-10
    • 2014-06-09
    相关资源
    最近更新 更多