Laravel 9 Many To Many | BelongsToMany Eloquent Relationship Tutorial (ok)

https://www.laravelia.com/post/laravel-9-many-to-many-belongstomany-eloquent-relationship-tutorial

C:\xampp\htdocs\songkhoe\routes\web.php

<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\TestController;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('/test/{id}', [TestController::class,'index']);
Route::get('/test2/{id}', [TestController::class,'index2']);
Route::get('/create/{id}', [TestController::class,'create']);
Route::get('/create2/{id}', [TestController::class,'create2']);

C:\xampp\htdocs\songkhoe\app\Http\Controllers\TestController.php

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\User;
use App\Models\Role;
class TestController extends Controller
{
  public function index($id)
  {
    $user = User::find($id);
    foreach ($user->roles as $role) {
      echo $role->name . "<br/>";
    }
  }
  public function index2($id)
  {
    $role = Role::find($id);
    foreach ($role->users as $user) {
      echo $user->name . "<br/>";
    }
  }
  public function create($id)
  {
    $user = User::find($id);
    $roleIds = [1, 2];
    $user->roles()->attach($roleIds);
  }
  public function create2($id)
  {
    $role = Role::find($id);
    $userIds = [7, 8,9];
    $role->users()->attach($userIds);
  }
}

C:\xampp\htdocs\songkhoe\database\seeders\DatabaseSeeder.php

<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\User;
use App\Models\Role;
use App\Models\RoleUser;
class DatabaseSeeder extends Seeder
{
  /**
   * Seed the application's database.
   *
   * @return void
   */
  public function run()
  {
    User::factory(10)->create();
    Role::factory(6)->create();
    RoleUser::factory(20)->create();
  }
}

C:\xampp\htdocs\songkhoe\database\migrations\2014_10_12_000000_create_users_table.php

<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUsersTable extends Migration
{
  /**
   * Run the migrations.
   *
   * @return void
   */
  public function up()
  {
    Schema::create('users', function (Blueprint $table) {
      $table->increments("id");
      $table->string('name');
    });
  }
  /**
   * Reverse the migrations.
   *
   * @return void
   */
  public function down()
  {
    Schema::dropIfExists('users');
  }
}

C:\xampp\htdocs\songkhoe\database\migrations\2022_11_18_042112_create_roles_table.php

<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateRolesTable extends Migration
{
  /**
   * Run the migrations.
   *
   * @return void
   */
  public function up()
  {
    Schema::create('roles', function (Blueprint $table) {
      $table->increments("id");
      $table->string('name');
    });
  }
  /**
   * Reverse the migrations.
   *
   * @return void
   */
  public function down()
  {
    Schema::dropIfExists('roles');
  }
}

C:\xampp\htdocs\songkhoe\database\migrations\2022_11_18_042240_create_role_user_table.php

<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateRoleUserTable extends Migration
{
  /**
   * Run the migrations.
   *
   * @return void
   */
  public function up()
  {
    Schema::create('role_user', function (Blueprint $table) {
      $table->integer("user_id");
      $table->integer("role_id");
    });
  }
  /**
   * Reverse the migrations.
   *
   * @return void
   */
  public function down()
  {
    Schema::dropIfExists('role_user');
  }
}

C:\xampp\htdocs\songkhoe\database\factories\UserFactory.php

<?php
namespace Database\Factories;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
class UserFactory extends Factory
{
  /**
   * The name of the factory's corresponding model.
   *
   * @var string
   */
  protected $model = User::class;
  /**
   * Define the model's default state.
   *
   * @return array
   */
  public function definition()
  {
    return [
      'name' => $this->faker->name()
    ];
  }
}

C:\xampp\htdocs\songkhoe\database\factories\RoleUserFactory.php

<?php
namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;
use App\Models\RoleUser;

class RoleUserFactory extends Factory
{
  protected $model = RoleUser::class;
  /**
   * Define the model's default state.
   *
   * @return array
   */
  public function definition()
  {
    return [
      "user_id" => $this->faker->numberBetween(1, 10),
      "role_id" => $this->faker->numberBetween(1, 6)
    ];
  }
}

C:\xampp\htdocs\songkhoe\database\factories\RoleFactory.php

<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
use App\Models\Role;
class RoleFactory extends Factory
{
  protected $model = Role::class;
  /**
   * Define the model's default state.
   *
   * @return array
   */
  public function definition()
  {
    return [
      "name" => $this->faker->firstName()
    ];
  }
}

C:\xampp\htdocs\songkhoe\app\Models\User.php

<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
  use HasFactory;
  public $timestamps = false;
  protected $fillable = [
    'name'
  ];
  /**
   * The roles that belong to the user.
   */
  public function roles()
  {
    return $this->belongsToMany(Role::class, 'role_user');
  }
}

C:\xampp\htdocs\songkhoe\app\Models\RoleUser.php

<?php
namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class RoleUser extends Model
{
  use HasFactory;
  protected $table = 'role_user';
  public $timestamps = false;
  protected $fillable = [
    'user_id',
    'role_id'
  ];
}

C:\xampp\htdocs\songkhoe\app\Models\Role.php

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Role extends Model
{
  use HasFactory;
  public $timestamps = false;
  protected $fillable = [
    'name'
  ];
  /**
   * The roles that belong to the user.
   */
  /**
   * The users that belong to the role.
   */
  public function users()
  {
    return $this->belongsToMany(User::class, 'role_user');
  }
}

Category : #laravel

Tags : #laravel, #laravel eloquent relationship

Laravel Many-to-many eloquent relationships are a little bit more complicated than hasOne and hasMany relationships. An example of many to many relationships is a user with may have multiple roles, where the role are also connected with multiple users. We can define many to many relationships by using belongToMany() helper with a pivot table.

So in this tutorial, you are going to learn 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.

laravel-9-many-to-many-relationship

Table Structure Of Many to Many

To define belongsToMany() relationship, three database tables are needed: users, roles, and role_user. The role_user table is called pivot table and derived from the alphabetical order of the related model names and contains user_id and role_id columns. This table will be used as an intermediate table linking the users and roles.

users
    id - integer
    name - string
 
roles
    id - integer
    name - string
 
role_user
    user_id - integer
    role_id - integer

MakefileCopy

Defining Many to Many Relationship

Many-to-many relationships can be defined by writing a method that returns the result of the belongsToMany method. So we can create a many to many relationship with roles for a user like:

app/Models/User.php

<?php
 
namespace App\Models;
 
use Illuminate\Database\Eloquent\Model;
 
class User extends Model
{
    /**
     * The roles that belong to the user.
     */
    public function roles()
    {
        return $this->belongsToMany(Role::class, 'role_user');
    }
}

PHPCopy

Now define the same relationship in the Role model:

app/Models/Role.php

<?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');
    }
}

PHPCopy

Read also: Laravel One To One/HasOne Eloquent Relationship Tutorial

Once the relationship is defined, you may access the user's roles using the roles dynamic relationship property:

App\Http\Controllers\TestController.php

<?php

namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\Http\Request;

class TestController extends Controller
{
    public function index($id)
    {   
        $user = User::find($id);

        foreach ($user->roles as $role) {
          //
        }
    }
}

PHPCopy

Create Records with Many to Many Relationship

If you want to save data with many to many relationships using eloquent, then we can use sync or attach method like:

App\Http\Controllers\TestController.php

<?php

namespace App\Http\Controllers;

use App\Models\Post;
use Illuminate\Http\Request;

class TestController extends Controller
{
    public function index($id)
    {   
        $user = User::find($id);	
 
        $roleIds = [1, 2];
        $user->roles()->attach($roleIds);
    }
}

PHPCopy

Or you can use sync also like:

App\Http\Controllers\TestController.php

<?php

namespace App\Http\Controllers;

use App\Models\Post;
use Illuminate\Http\Request;

class TestController extends Controller
{
    public function index($id)
    {   
       $user = User::find($id);	
 
       $roleIds = [1, 2];
       $user->roles()->sync($roleIds);
    }
}

Last updated

Was this helpful?