When there’s Many-to-Many relationships, the pivot concept will come into the picture.
e.g.
Many-to-Many relationship for post and tags, a post has many tags, or tag has many posts
Table structure for the many to many relationship with pivot table is as follows:
posts id - integer title - string tags id - integer title - string post_tag post_id - integer tag_id - integer
Many-to-many relationships are defined by writing a method that returns the result of the belongsToMany method. For example, let’s define the tags method on our Post model:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Post extends Model { /** * The tags that belong to the post. */ public function tags() { // return $this->belongsToMany('App\Tag'); return $this->belongsToMany('App\Tag', 'post_tag', 'post_id', 'tag_id'); } }
Once the relationship is defined, you may access the post’s tags using the tags dynamic property:
$post = App\POST::find(1); foreach ($post->tags as $tag) { // }
By default, only the model keys will be present on the pivot object. If your pivot table contains extra attributes, you must specify them when defining the relationship:
return $this->belongsToMany('App\Tag')->withPivot('column1', 'column2');
If you want your pivot table to have automatically maintained created_at and updated_at timestamps, use the withTimestamps method on the relationship definition:
return $this->belongsToMany('App\Tag)->withTimestamps();
Eloquent provides a few additional helper methods to make working with related models more convenient. For example, let’s imagine a post can have many tags and a tag can have many posts. To attach a tag to a post by inserting a record in the intermediate table that joins the models, use the attach method
$post = App\Post::find(1); $post->tags()->attach($tagId);
When attaching a relationship to a model, you may also pass an array of additional data to be inserted into the intermediate table:
Sometimes it may be necessary to remove a tag from a post. To remove a many-to-many relationship record, use the detach method. The detach method will delete the appropriate record out of the intermediate table; however, both models will remain in the database:
// Detach a single tag from the post… $post->tags()->detach($tagId); // Detach all tags from the post… $post->tags()->detach();
For convenience, attach and detach also accept arrays of IDs as input:
$post = App\Post::find(1); $post->tags()->detach([1, 2, 3]);
You may also use the sync method to construct many-to-many associations. The sync method accepts an array of IDs to place on the intermediate table. Any IDs that are not in the given array will be removed from the intermediate table. So, after this operation is complete, only the IDs in the given array will exist in the intermediate table:
$post->tags()->sync([1, 2, 3]);
You may also pass additional intermediate table values with the IDs:
$post->tags()->sync([1 => ['expires' => true], 2, 3]);
If you do not want to detach existing IDs, you may use the syncWithoutDetaching method:
$post->tags()->syncWithoutDetaching([1, 2, 3]);
The many-to-many relationship also provides a toggle method which “toggles” the attachment status of the given IDs. If the given ID is currently attached, it will be detached. Likewise, if it is currently detached, it will be attached:
$post->tags()->toggle([1, 2, 3]);
When working with a many-to-many relationship, the save method accepts an array of additional intermediate table attributes as its second argument:
App\Post::find(1)->tags()->save($tag, ['expires' => $expires]);
If you need to update an existing row in your pivot table, you may use updateExistingPivot method. This method accepts the pivot record foreign key and an array of attributes to update:
$post = App\Post::find(1); $post->tags()->updateExistingPivot($tagId, $attributes);