Reputation: 1421
I am having an issue getting a hasManyThrough to work:
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);
}
Because the stockMovements table returns multiple results, my resulting delivery containers collection contains duplicate entries. If I could somehow put a group/unique on the intermediate table query then this would be resolved.
I can get a collection with the correct deliveryContainers eager loaded using the following:
public function deliveryContainers()
{
return $this->hasMany(StockMovement::class, 'entity_id', 'delivery_id')
->with('deliveryContainer')
->where('product_id', $this->product_id)
->get()
->unique('location_id');
}
However, to access the deliveryContainer I now have the following:
foreach($this->deliveryContainers() as $row){
$row->deliveryContainer->id;
}
And what I would like to have...
foreach($this->deliveryContainers() as $row){
$row->id;
}
Is there any way to push the eager loaded relationship up a level (if that can be used to describe it), or even better add some kind of unique filter to the hasManyThrough relationship?
Table Structure
delivery_exceptions (where this relationship originates)
delivery_containers
stock_movements
Relationships
Upvotes: 2
Views: 4381
Reputation: 1421
The accepted answer is far more elegant, but this is another way to do this too:
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();
}
Upvotes: 2
Reputation: 6544
You've got a really tough setup there and I'm not entirely sure that I got the full idea behind it (also because of you using entity_id
at some place instead of delivery_id
). But nonetheless, I gave it a shot.
The hasManyThrough
relationship you defined looks actually not too bad, but in my opinion there is a better way to get to the result. But first let's have a look at your relationships:
3
+-------------------------------------+
4 v |
+-------------> Delivery <----------+ |
| | 1 |
+ + +
DeliveryException +---> Product <---+ StockMovement +---> DeliveryContainer
+ ^
+---------------------------------------------------------+
2
As a StockMovement
already belongs to a DeliveryContainer
, which in return belongs to a Delivery
, the relation from StockMovement
to Delivery
(marked as 1
) seems obsolete to me. Anyway, to get relation 2
on your model, you can use the paths 3
and 4
to your advantage:
class DeliveryException
{
public function deliveryContainers(): HasMany
{
return $this->hasMany(DeliveryContainer::class, 'delivery_id', 'delivery_id');
}
}
Obviously, this will give you all the DeliveryContainers
, unfiltered by the Product
. Therefore I suggest adding a second function:
public function deliveryContainersByProduct(): HasMany
{
return $this->deliveryContainers()
->whereHas('stockMovements', function ($query) {
$query->where('product_id', $this->product_id);
});
}
Upvotes: 3