Implementing Many-to-Many Relationships in Laravel 11

Apr 20, 2024 | Laravel 11 Laravel


Hello Dev,

In Laravel, demonstrating a many-to-many relationship in a Laravel 11 application involves utilizing the `belongsToMany()` Eloquent method.

Consider the relationship between tables like "users" and "roles": in this setup, each user can be associated with multiple roles, and conversely, each role can be linked to multiple users. The intermediary table, typically named "role_user," serves as a bridge to store these connections between users and roles.

This configuration offers flexibility in assigning roles, allowing users to possess different roles and roles to be shared across multiple users. This approach simplifies the management of permissions and access levels within applications.

To implement a many-to-many relationship in Laravel 11 between "users" and "roles" tables, you'll use the belongsToMany() method provided by Eloquent ORM. This relationship is particularly useful for scenarios where each user can have multiple roles, and each role can be assigned to multiple users. The pivot table, often named role_user, is used to manage these relationships.

Step 1: Generate Migrations

First, ensure you have the users and roles tables in your database. If not, you can create them using migrations. Additionally, you'll need a pivot table to manage the many-to-many relationship. By convention, Laravel uses the singular names of the two related tables, in alphabetical order, separated by an underscore.

php artisan make:migration create_users_table
php artisan make:migration create_roles_table
php artisan make:migration create_role_user_table
Read Also: implementing one-to-many relationships in laravel 11 Step 2: Define the Schema for the Pivot Table

In the create_role_user_table migration, define the schema for the pivot table. It should include foreign keys referencing the users and roles tables.

users 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(): void
    {
        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down(): void
    {
        Schema::dropIfExists('users');
    }
};
roles 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(): void
    {
        Schema::create('roles', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->timestamps();
        });
    }
  
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down(): void
    {
        Schema::dropIfExists('roles');
    }
};
role_user 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(): void
    {
        Schema::create('role_user', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id')->constrained()->onDelete('cascade');
            $table->foreignId('role_id')->constrained()->onDelete('cascade');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down(): void
    {   
        Schema::dropIfExists('role_user');
    }
};
Step 3: Define the Relationships in the Models

In the User model, define the roles method to establish the many-to-many relationship.

User Model:
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;

class User extends Authenticatable
{
    use HasFactory, Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name',
        'email',
        'password',
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var array
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    /**
     * Get the attributes that should be cast.
     *
     * @return array
     */
    protected function casts(): array
    {
        return [
            'email_verified_at' => 'datetime',
            'password' => 'hashed',
        ];
    }

    /**
     * The roles that belong to the user.
     */
    public function roles(): BelongsToMany
    {
        return $this->belongsToMany(Role::class, 'role_user');
    }
}
Role Model:
<?php
  
namespace App\Models;
  
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
  
class Role extends Model
{
    use HasFactory;
  
    /**
     * The users that belong to the role.
     */
    public function users(): BelongsToMany
    {
        return $this->belongsToMany(User::class, 'role_user');
    }
}
UserRole Model:
<?php
  
namespace App\Models;
  
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
  
class UserRole extends Model
{
    use HasFactory;
      
}
Read Also: building dynamic charts with chart.js in laravel 11 Step 4: Accessing Related Models

With the relationships defined, you can now easily access roles for a specific user and users for a specific role.

Accessing Roles for a User:
$user = App\Models\User::find(1); // Find a user by its ID
$roles = $user->roles; // Access the roles for the user
Accessing Users for a Role:
$role = App\Models\Role::find(1); // Find a role by its ID
$users = $role->users; // Access the users for the role

By following these steps, you've established a many-to-many relationship between the "users" and "roles" tables in your Laravel 11 application, allowing for flexible role assignments and management of permissions and access levels

Thank you for your encouragement! If you have any questions or need further assistance, feel free to ask. I'm here to help!



Tags :
#Laravel 11
#Laravel
ItErrorSolution.com

ItErrorSolution.com

"Hey there! I'm a full-stack developer and proud owner of ItErrorSolution.com, based right here in India. I love nothing more than sharing handy tips and tricks with my fellow developers through easy-to-follow tutorials. When it comes to coding, I'm all about PHP, Laravel, Angular, Vue, Node, JavaScript, jQuery, CodeIgniter, and Bootstrap – been hooked on them forever! I'm all about putting in the work and staying committed. Ready to join me on this journey to coding?"