Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Has many through many-to-many

Tags:

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!

like image 607
ntzm Avatar asked May 25 '16 07:05

ntzm


People also ask

How do you avoid a many to many relationship?

To avoid this problem, you can break the many-to-many relationship into two one-to-many relationships by using a third table, called a join table. Each record in a join table includes a match field that contains the value of the primary keys of the two tables it joins.

What is with () in Laravel?

with() function is used to eager load in Laravel. Unless of using 2 or more separate queries to fetch data from the database , we can use it with() method after the first command. It provides a better user experience as we do not have to wait for a longer period of time in fetching data from the database.

What is polymorphic relationship Laravel?

A one-to-one polymorphic relationship is a situation where one model can belong to more than one type of model but on only one association. A typical example of this is featured images on a post and an avatar for a user. The only thing that changes however is how we get the associated model by using morphOne instead.

What is belongsTo in Laravel?

BelongsTo relationship in laravel is used to create the relation between two tables. belongsTo means create the relation one to one in inverse direction or its opposite of hasOne. For example if a user has a profile and we wanted to get profile with the user details then we can use belongsTo relationship.


2 Answers

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

public function metrics() {     return Metric      ::join('metric_product', 'metric.id', '=', 'metric_product.metric_id')      ->join('products', 'metric_product.product_id', '=', 'products.id')      ->join('deal_product', 'products.id', '=', 'deal_product.product_id')      ->join('deals', 'deal_product.deal_id', '=', 'deal.id')      ->where('deal.id', $this->id);  }   // you can access to $deal->metrics and use eager loading public function getMetricsAttribute() {     if (!$this->relationLoaded('products') || !$this->products->first()->relationLoaded('metrics')) {         $this->load('products.metrics');     }      return collect($this->products->lists('metrics'))->collapse()->unique(); } 

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.

like image 193
mpur Avatar answered Nov 26 '22 07:11

mpur


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

class User extends Model {     use \Staudenmeir\EloquentHasManyDeep\HasRelationships;      public function permissions()     {         return $this->hasManyDeep(             'App\Permission',             ['role_user', 'App\Role', 'permission_role'], // Pivot tables/models starting from the Parent, which is the User         );     } } 

Example if foreign keys need to be defined:

https://github.com/staudenmeir/eloquent-has-many-deep/issues/7#issuecomment-431477943

like image 20
Nickson Yap Avatar answered Nov 26 '22 08:11

Nickson Yap