Relación many-to-many personalizada en Laravel

Publicado por Lynn
hace 6 meses

Tengo una tabla llamada "usuarios" y otra tabla llamada "roles". Quiero establecer una relación many-to-many entre estas dos tablas, pero necesito agregar un atributo adicional a la tabla pivot. ¿Cómo puedo hacer esto en Laravel?

He intentado utilizar el método "belongsToMany" en el modelo de "Usuario" y en el modelo de "Rol", pero no encuentro una forma de agregar el atributo adicional en la tabla pivot.

¿Alguien puede ayudarme con esto? Agradezco cualquier orientación o ejemplo de código que puedan proporcionarme. Gracias de antemano.

Laravel relaciones tabla pivot
Respuesta de Gordon Shumway
hace 6 meses

¡Hola Lynn!

Agregar un atributo adicional a la tabla pivot en una relación de muchos a muchos en Laravel es relativamente sencillo. Primero, asegúrate de que tu tabla pivot (usualmente llamada role_user si sigues la convención de nombres de Laravel para tablas pivot muchas a muchas) tenga las columnas adicionales que necesitas.

Digamos que quieres agregar un atributo expires_at a la tabla pivot. Tu migración podría verse así:

Schema::create('role_user', function (Blueprint $table) {
    $table->unsignedBigInteger('user_id');
    $table->unsignedBigInteger('role_id');
    $table->timestamp('expires_at')->nullable(); // tu columna adicional
    $table->timestamps();

    $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
    $table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade');

    $table->primary(['user_id', 'role_id']);
});

Luego, en tu modelo Usuario, puedes especificar la relación así:

public function roles()
{
    return $this->belongsToMany(Role::class)
                ->withPivot('expires_at')  // Aquí especificamos la columna adicional
                ->withTimestamps(); // Si también deseas que la tabla pivot maneje timestamps
}

De manera similar, en tu modelo Rol, la relación sería:

public function users()
{
    return $this->belongsToMany(User::class)
                ->withPivot('expires_at')  // Aquí también especificamos la columna adicional
                ->withTimestamps();
}

Cuando quieras agregar un rol a un usuario con ese atributo adicional, podrías hacer lo siguiente:

$user->roles()->attach($roleId, ['expires_at' => $expiresAtValue]);

Y para actualizar ese valor adicional:

$user->roles()->updateExistingPivot($roleId, ['expires_at' => $newExpiresAtValue]);

Recuerda reemplazar $roleId con la ID del rol real y $expiresAtValue y $newExpiresAtValue con el valor real de la fecha de expiración que quieres establecer.

¡Espero que esto te ayude!