Helen Che
Helen Che

Reputation: 2011

Is this many-to-many relationship possible in Laravel?

I'm trying to get my head around using polymorphic relationships for a many-to-many relationship between suppliers and products:

products
  id
  name
suppliers
  id
  name

product_supplier
  id
  product_id        // belongsToMany easily takes care of this id
  supplier_id       // and this id
  price             // this can be fetched using withPivot('price')
  deliverymethod_id // I'm having difficulties "joining" this one.

I'm confident in using belongsToMany(), I can easily do something like this:

public function products()
{
    return $this
    ->belongsToMany('Supplier')
    ->withPivot('price');
}

But the catch here is joining to that third column in the relationship table:

deliverymethods
  id
  name

I am unsure how to do this. I've been told that Polymorphic Relationships are what I'm after however I'm unsure how to implement them for my situation.

http://laravel.com/docs/4.2/eloquent#many-to-many-polymorphic-relations

According to the documentation, I would have to rename my table columns to include *able_id and *able_type. This is really confusing.

I was expecting laravel to having something like belongsToMany('Supplier')->withAlso('Deliverymethod')

Upvotes: 2

Views: 341

Answers (1)

sisou
sisou

Reputation: 323

I'm afraid that method does not exist (yet?).

What I fall back to is manually filling in the 3rd relation:

public function products()
{
    return $this
    ->belongsToMany('Supplier')
    ->withPivot('price', 'delivermethod_id');
}

Now I can access ->pivot->deliverymethod_id on every Product that I get via Supplier.

You could even add a function in your Product model that fills this in automatically:

Class Product ... {

protected $appends = array('deliverymethod');

public function getDeliverymethodAttribute()
{
    return Deliverymethod::find($this->pivot->delivermethod_id);
}

Now every time you request a product via it's relation to the supplier, it automatically includes a deliverymethod attribute with the object in it.

(To have it not throw an error when you get a Product directly, just remove the $appends variable from the Product model and call the getDeliverymethodAttribute() method manually whenever you need it.)

Short explanation about polymorphic relations:

Polymorphic relations are for relations, where two models are related to a third model at the same time. So for example both a User and a Product can have a Picture of them. Now, it doesn't make sense to have two models for the pictures (UserPicture and ProductPicture), since they both have the same characteristics. This would be a perfect reason to use a polymorphic relation, where the Picture can both belong to a User or a Product.

However, in your case the Deliverymethod applies directly to the relation between Supplier and Product. So this is not where polymorphic relations would work, but it has instead to be done the way you did it.

Upvotes: 2

Related Questions