Laravel-建立HasManyThrough关系提供了一个独特的集合

时间:2018-11-09 20:10:56

标签: php laravel eloquent has-many-through

我在获取hasManyThrough上班时遇到问题:

public function deliveryContainers() : HasManyThrough
{
    return $this->hasManyThrough(
        DeliveryContainer::class, // Final
        StockMovement::class, // Intermediate
        'product_id', // Foreign key on Intermediate
        'id', // Foreign key on Final
        'product_id', // Local key on Current
        'location_id' // Local key on Intermediate
    )->where('delivery_id', $this->delivery_id);
}

由于stockMovements表返回多个结果,因此我得到的交付容器集合包含重复的条目。如果我能以某种方式在中间表查询上放置一个组/唯一性,那么这将得到解决。

我可以使用以下方法加载具有正确的deliveryContainers的集合:

public function deliveryContainers()
{
    return $this->hasMany(StockMovement::class, 'entity_id', 'delivery_id')
        ->with('deliveryContainer')
        ->where('product_id', $this->product_id)
        ->get()
        ->unique('location_id');
}

但是,要访问deliveryContainer,我现在具有以下内容:

foreach($this->deliveryContainers() as $row){
    $row->deliveryContainer->id;    
}

还有我想拥有的...

foreach($this->deliveryContainers() as $row){
    $row->id;
}

有什么办法可以将渴望加载的关系提升到一个更高的水平(如果可以用来描述它的话),或者甚至更好地为hasManyThrough关系添加某种独特的过滤器?

表结构

delivery_exceptions(发生这种关系的地方)

  • product_id
  • delivery_id

delivery_containers

  • id
  • delivery_id

stock_movements

  • entity_id(链接到交货ID)
  • product_id

关系

  • 交货例外属于产品
  • 一个产品有很多库存变动
  • 库存移动属于送货容器
  • 交货例外有许多交货容器 ...(间接地,通过产品和库存移动的组合)

2 个答案:

答案 0 :(得分:1)

您在那里进行了非常困难的设置,但我不确定是否完全了解它的全部含义(也是因为您在某个地方使用entity_id而不是delivery_id)。但是,尽管如此,我还是给了它一个机会。

您定义的hasManyThrough关系实际上看起来还不错,但是我认为有一种更好的方法可以得到结果。但首先让我们看一下您的关系:

                                               3
                            +-------------------------------------+
               4            v                                     |
        +-------------> Delivery <----------+                     |
        |                                   | 1                   |
        +                                   +                     +
DeliveryException +---> Product <---+ StockMovement +---> DeliveryContainer
        +                                                         ^
        +---------------------------------------------------------+
                                      2

由于StockMovement已经属于DeliveryContainer,而后者又属于Delivery,因此从StockMovementDelivery的关系(标记为{ {1}})对我来说似乎已经过时了。无论如何,要在模型上获得关系1,可以利用路径23来发挥自己的优势:

4

很显然,这将为您提供所有class DeliveryException { public function deliveryContainers(): HasMany { return $this->hasMany(DeliveryContainer::class, 'delivery_id', 'delivery_id'); } } ,而不受DeliveryContainers的过滤。因此,我建议添加第二个功能:

Product

答案 1 :(得分:0)

公认的答案要优雅得多,但这也是实现此目的的另一种方法:

public function deliveryContainers1()
{
    return $this->hasManyThrough(
        DeliveryContainer::class, // Final
        StockMovement::class, // Intermediate
        'product_id', // Foreign key on Intermediate
        'id', // Foreign key on Final
        'product_id', // Local key on Current
        'location_id' // Local key on Intermediate
    )
        ->where('delivery_id', $this->delivery_id)
        ->distinct();
}