In this tutorial, i would like to explain many to many model relationship in laravel. Many to many relationship is a little bit complicated than one to one and one to many relationships. An example of such a relationship is a user with may have multiple roles, where the role are also connected with multiple users.
In this example, you can understand how to create many-to-many relationships with migration with a foreign key schema for one to many relationships, use sync with a pivot table, create records, attach records, get all records, delete, update, where condition and everything related to many to many relationship.
Many to Many Relationship will use "belongsToMany()" for relation.
In this example, i will create "users", "roles" and "role_user" tables. each table is connected with each other. now we will create many to many relationships with each other by using the laravel Eloquent Model. We will first create database migration, then model, retrieve records and then how to create records too.
Create Migrations:
users table migration:
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
roles table migration:
Schema::create('roles', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
role_user table migration:
Schema::create('role_user', function (Blueprint $table) {
$table->integer('user_id')->unsigned();
$table->integer('role_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users')
->onDelete('cascade');
$table->foreign('role_id')->references('id')->on('roles')
->onDelete('cascade');
});
Create Models:
Here, we will create User, Role and UserRole table model. we will also use "belongsToMany()" for relationship of both model.
User Model:
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* The roles that belong to the user.
*/
public function roles()
{
return $this->belongsToMany(Role::class, 'role_user');
}
}
Role Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Role extends Model
{
/**
* The users that belong to the role.
*/
public function users()
{
return $this->belongsToMany(User::class, 'role_user');
}
}
Defining Custom Intermediate Table Models:
If you would like to define a custom model to represent the intermediate table of your relationship, you may call the using
method when defining the relationship. Custom many-to-many pivot models should extend the Illuminate\Database\Eloquent\Relations\Pivot
class while custom polymorphic many-to-many pivot models should extend the Illuminate\Database\Eloquent\Relations\MorphPivot
class. For example, we may define a Role
which uses a custom RoleUser
pivot model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Role extends Model
{
/**
* The users that belong to the role.
*/
public function users()
{
return $this->belongsToMany('App\User')->using('App\RoleUser');
}
}
<?php
namespace App;
use Illuminate\Database\Eloquent\Relations\Pivot;
class UserRole extends Pivot
{
}
You can combine using
and withPivot
in order to retrieve columns from the intermediate table. For example, you may retrieve the created_by
and updated_by
columns from the RoleUser
pivot table by passing the column names to the withPivot
method:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Role extends Model
{
/**
* The users that belong to the role.
*/
public function users()
{
return $this->belongsToMany('App\User')
->using('App\RoleUser')
->withPivot([
'created_by',
'updated_by',
]);
}
}
Retrieve Records:
Retrieve roles from User object:
$roles = User::find(1)->roles;
Retrieve users from Role object:
$users = Role::find(1)->users;
Like all other relationship types, you may call the roles
method to continue chaining query constraints onto the relationship:
$roles = App\User::find(1)->roles()->orderBy('name')->get();
Create Records:
Example 1:
$user = User::find(2);
$roleIds = [1, 2];
$user->roles()->attach($roleIds);
Example 2:
$user = User::find(3);
$roleIds = [1, 2];
$user->roles()->sync($roleIds);
Example 3:
$role = Role::find(1);
$userIds = [10, 11];
$role->users()->attach($userIds);
Example 4:
$role = Role::find(2);
$userIds = [10, 11];
$role->users()->sync($userIds);
Retrieving Intermediate Table Columns:
$user = App\User::find(1);
foreach ($user->roles as $role) {
echo $role->pivot->created_at;
}
Filtering Relationships Via Intermediate Table Columns
You can also filter the results returned by belongsToMany
using the wherePivot
, wherePivotIn
, and wherePivotNotIn
methods when defining the relationship:
return $this->belongsToMany('App\Role')->wherePivot('approved', 1);
return $this->belongsToMany('App\Role')->wherePivotIn('priority', [1, 2]);
return $this->belongsToMany('App\Role')->wherePivotNotIn('priority', [1, 2]);
I hope you found this article useful. let me know if you have any questions and I’ll be happy to answer them.