I have the following table layout:
deals:
- id
- price
products:
- id
- name
deal_product:
- id
- deal_id
- product_id
metrics:
- id
- name
metric_product:
- id
- metric_id
- product_id
- value
products
and metrics
have a many-to-many relationship with a pivot column of value.
deals
and products
also have a many-to-many relationship.
I can get metrics for a product with $product->metrics
, but I want to be able to get all metrics for all products related to a deal, so I could do something like this: $deal->metrics
.
I currently have the following in my Deal
model:
public function metrics()
{
$products = $this->products()->pluck('products.id')->all();
return Metric::whereHas('products', function (Builder $query) use ($products) {
$query->whereIn('products.id', $products);
});
}
But this doesn't return a relationship, so I cannot eager load it or get related models from it.
It needs to be in relationship format, because they need to be eager loaded for my use case.
Thanks for your help!
If you want to have a custom relation, you can create your own extends to Relation abstract class. For example:
BelongsToManyThought
.But if you don't want to implement a Relation, I think that it can fulfill your needs :
In App\Deal.php, you can combine the solution of @thomas-van-der-veen
You can refer to this post to see how you can simply use nested relations.
This solution can do the trick for querying relation with method and access to metrics attribute.
This should do the trick:
The Models/Product.php file:
the Models/Deal.php file:
the Models/Metric.php file:
From your controller:
Now you have a collection of deals with products, and their related metrics. See the docs for nested eager loading.
There is no "Many to Many Through" method available.
To get all Metrics available in all Products for a certain Deal, create a getter to Eager Load all Products and Metrics for the Deal, and leverage Laravel's Collections methods.
In your
Deal
model:You can then get the metrics for a Deal with
$deal->getMetrics()
This will return a Collection of Metrics objects, which should be exactly what you are looking for.
In case someone still needs it:
First you will eager load products and metrics
in deal model
now you can get all metrics of products of a deal by:
There is a Laravel 5.5 composer package that can perform multi-level relationships (deep)
Package: https://github.com/staudenmeir/eloquent-has-many-deep
Example:
User
→ belongs to many →Role
→ belongs to many →Permission
Example if foreign keys need to be defined:
https://github.com/staudenmeir/eloquent-has-many-deep/issues/7#issuecomment-431477943
I don't have enough rep to post a comment so I'll post an answer instead.
A few days ago I posted a similar question and was able to answer it myself. I think the solution also works for this question.
By joining the tables manually and add a where clause you are able to retrieve the desired Metrics.
Possible solution:
Hope this helps :)
Edit after @ntzm comment
If you only need some properties of the metrics table and none of the Model functionalities you can add a select('*') before the joins.
Like this:
It will return a Metric model with all the attributes of the joined tables.
This example will return an object like:
Since there are a lot of columns with the same name you won't be able to access these values. However you can multiple selects and rename the columns in your results.
Like this:
This will result in something like:
I hope this will solve something :) Of course there are much cleaner ways to solve your problem.