Eloquent Relationships: Many To Many

Many To Many Relationships

We will look at the article and the tags that are attached to the article as an example.

Table Structure

To define this type of relationship, we need three database tables: articles, tags, and intermediate table article_tag. The article_tag table's name must contain the names of the models in alphabetical order and has id models columns.

articles
    id - integer
    name - string
 
tags
    id - integer
    name - string
 
article_tag
    article_id - integer
    tag_id - integer

Model Structure

Now we will define a method through which we can get all the tags for the article using the intermediate table.

<?php
 
declare(strict_types=1);
 
namespace App\Models;
 
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
 
class Article extends Model
{
    /**
     * The tags that belong to the article.
     */
    public function tags() : BelongsToMany
    {
        return $this->belongsToMany(Tag::class);
    }
}

We can also get all articles that contain a certain tag. Let's add a method to the tag model.

public function articles() : BelongsToMany
{
	return $this->belongsToMany(Article::class);
}

Access to model dynamic relationship property

You may access the article tags using the roles dynamic relationship property

$article = Article::find($id);
 
foreach ($article->tags as $tag) {
    //
}

$tag = Tag::find($id);
 
foreach ($tag->articles as $article) {
    //
}

Access to model method

$tags = Article::find($id)->tags()->orderBy('name')->get();

$articles = Tag::find($id)->articles()->orderBy('updated_at', 'desc')->paginate(10);

Attaching relationships

You may create a tag model and then use the attach method for creating rows in the intermediate table.

/**
 * Tag Attach
 *
 * @param Article $article
 * @param StoreRequest $request
 *
 * @return void
 */
public function attach(Article $article, StoreRequest $request) : void
{
	$tag = Tag::create($request->validated());

	$article->tags()->attach($tag->id);
}

Detaching relationships

To remove the relationship between tag and article, use the detach method.

// Detach a single tag from the article
$article->tags()->detach($tag->id);
 
// Detach all tags from the article
$article->tags()->detach();

Syncing Associations

Also, you can use the sync method to remove all relationships between tags and certain article, then add new relationships from the array.

$tagIds = [1, 2, 3];

$article->tags()->sync($tagIds);

You can use the syncWithoutDetaching method if you don't want to detach existing IDs that are missing from the specified array.

$article->tags()->syncWithoutDetaching([$tag->id]);

$tagIds = [1, 2, 3];

$article->tags()->syncWithoutDetaching($tagIds);