Laravel Many to Many Relationship Example
Laravel many to many relationship is a bit more complicated than hasOne and hasMany, a good example of this relationship is a post that has many tags and those tags are also shared by other posts in the application.
In this tutorial, we will create Post Tag many-to-many relationship first, let's create the migrations.
Create the posts table migration
I assume that you already know how to create Laravel migrations, so let's create a posts table migration.
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('body');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('posts');
}
};
Create the tags table migration
Next, let's create the tags table migration.
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('tags', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('tags');
}
};
Create the post_tag table migration
Next, let's create the post_tag table migration.
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('post_tag', function (Blueprint $table) {
$table->id();
$table->foreignId('tag_id')->constrained();
$table->foreignId('post_id')->constrained();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('post_tag');
}
};
Add relationships in models
Next, we define the relationships in the models.
//post model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use HasFactory;
public function tags(){
return $this->belongsToMany(Tag::class);
}
}
//tag model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Tag extends Model
{
use HasFactory;
public function posts(){
return $this->belongsToMany(Post::class);
}
}
Create and retrieve the data
So to save the tags we use attach or sync and to display the data we use the tags relationship property.
//save the data
/**
* Store a newly created resource in storage.
*
* @param \App\Http\Requests\StorePostRequest $request
* @return \Illuminate\Http\Response
*/
public function store(StorePostRequest $request)
{
//
if($request->validated()){
$data = $request->all();
$post = Post::create($data);
//use sync
$post->tags()->sync($request->tags);
//or attach
$post->tags()->attach($request->tags);
return redirect()->route('posts.index')->with([
'success' => 'Post added successfully'
]);
}
}
//retrieve the data
@foreach ($post->tags as $tag)
<span class="badge bg-dark mx-2">
{{$tag->name}}
</span>
@endforeach