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.

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