Laravel Many to Many Relationship Tutorial

Afraz Ahmad
3 min readMar 3, 2020

--

Many To Many (e.g. User can win multiple Trophies and each trophy can belong to many Users)

Steps

1 — Models classes and Tables
2 — Migrations
3 — Defining Relationships in Modal classes
4 — Fetch/Create/Update/Delete Records

Models classes and Tables

1- User Model and users table
2- Trophy Model and trophies table
3- trophies_users pivot table

Migrations

Run below command in the console to create model and table

php artisan make:model User -m   //create users table and User Model
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('full_name');
$table->string('email');
$table->string('password')->nullable();
$table->rememberToken();
$table->timestamps();
});
}

/**
* Reverse the migrations.
*
*
@return void
*/
public function down()
{
Schema::dropIfExists('users');
}
php artisan make:model Trophy -m   //create trophies table and Trophy Model
public function up()
{
Schema::create('trophies', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
});
}

/**
* Reverse the migrations.
*
*
@return void
*/
public function down()
{
Schema::dropIfExists('trophies');
}
php artisan make:migration create_trophies_users_table
public function up()
{
Schema::create('trophies_users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('user_id');
$table->foreign('user_id')
->references('id')
->on('users')->onDelete('cascade');
$table->string('trophy_id');
$table->foreign('trophy_id')
->references('id')
->on('trophies')->onDelete('cascade');
});
}

/**
* Reverse the migrations.
*
*
@return void
*/
public function down()
{
Schema::dropIfExists('trophies_users');
}

Define Relationships in model classes

In User model class, define trophies relationship

public function trophies()
{
//return $this->belongsToMany(RelatedModel, pivot_table_name, foreign_key_of_current_model_in_pivot_table, foreign_key_of_other_model_in_pivot_table);
return $this->belongsToMany(
Trop::class,
'trophies_users',
'user_id',
'trophy_id');
}

Now in Trophy model class, define users relationship.

public function users()
{
//return $this->belongsToMany(RelatedModel, pivot_table_name, foreign_key_of_current_model_in_pivot_table, foreign_key_of_other_model_in_pivot_table);
return $this->belongsToMany(
User::class,
'trophies_users',
'trophy_id',
'user_id');
}

Fetch/Create/Update/Delete Records

Fetch: Suppose we want to get user’s trophies then we can do it in the following ways.

To trophies in a collection

User::find(1)->trophies;
//Or We can find user and get tropheis
$user = User::find(1);
$user->trophies; //it will return collection

To an eloquent query on trophies relationship

$user->trophies();       //it is in eloquent so you chain your query$user->trophies()
->whereName('any name of trophy')
->wherePivot('created_at','>',today());

Get Users who have at least 2 or more trophies

$users = User::whereHas('trophies','>',2)->get();foreach($users as $user){

$user->trophies; //we can get trophies of each user
}

Create: Record in pivot table. attach or syncWithoutDetaching

Get a user and call relationship to save data in the database.

$user = User::find(1); //any user we want to find $user->trophies()->attach($idOfTrophy); 
//pass id or array of a Trophy ids
//suppose admin has selected the trophy from a form and trophy id
// is in $request object, then.
$trophyId = $request->trophy_id;$user->trophies()->attach($trophyId); //record is created in DB.attach and syncWithoutDetaching both does same job

Suppose you have an extra column in a pivot table and you want to add data in it while creating a record then you can do it like this.

$user->trophies()
->attach($trophyId,['column_name_in_pivot','any_value you want']);
It will create record with additional column data.

Delete: Records from a pivot table

To delete all records:

$user->trophies()->detach(); //leave the detach function empty

To delete records having given trophy ids

$trophyIds  = Trophy::where('some_column','some_value')
->pluck('id')->toArray();
//it will give array of ids.$user->trophies()->detach($trophyIds); //deletes given trophies of $user

To remove previous trophies and add new

...sync([])                 // remove old records and add new 
// sync function requires array.
$user->trophies()->sync($trophyIds);
...
It will remove add trophies of this $user and add new trophies.

If we pass an empty array to sync then it will delete old records but do not create new since the array is empty. So sync([]) with empty array will behave the same like detach()

$user->trophies()->sync($trophyIds); 
//remvoe old records and do not add new

If trophies of given ids are already added then delete them else create them

//support below are ids of trophies$trophyIds = [1, 2, 3];$user->trophies()->toggle($trophyIds);

Update: Records from pivot table

If you want to update and existing record in pivot table.

$trophyId = //trphy id that you want to update.
$attributes = ['column_name', 'some_new_value'];
$user->trophies()->updateExistingPivot($trophyId, $attributes);It will update the existing record where trophy id is equal to given.It will change the values that you have passed in array in second parameter.

--

--