ManyToMany-Muchos a muchos
Para este tutorial se usará de ejemplo un sistema que gestiona alumnos en una escuela, este sistema cuenta con dos modelos, Estudiante y Curso en donde un estudiante puede tener muchos cursos y un curso puede contar con muchos estudiantes.En este ejemplo aplica la relación de «muchos a muchos». En los siguientes pasos verás cómo implementar las relaciones «muchos a muchos» (Many to Many) en Laravel.
Configurar migraciones
Cuando trabajas con relaciones de muchos a muchos es necesario crear una tabla intermedia o pivote la cual relaciona el id del modelo Estudiante y el id del modelo Curso. Primero crea el modelo Estudiante y su migración, para ello abre una terminal de comandos en la raíz de tu proyecto en Laravel y ejecuta la instrucción:
php artisan make:model Estudiante -m
Para crear el modelo Curso y su migración:
php artisan make:model Curso -m
Ahora para crear la tabla intermedia o tabla pivote recuerda que debe ser llamada como los modelos y en orden alfabético en este caso se llama curso_estudiante ya que curso es primero alfabéticamente que estudiante y siempre en singular. Ejecuta el siguiente comando:
php artisan make:migration create_curso_estudiante_table
Configurar migraciones
Con el editor de textos de tu preferencia abre el archivo database/migrations/…create_estudiantes_table.php y agrega el campo ‘name’ y ‘first_name’ para que quede así:
Schema::create('estudiantes', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('last_name');
$table->timestamps();
});
Toca configurar el archivo database/migrations/…create_cursos_table.php al cual para este ejemplo solo le agregarás el campo ‘name’:
Schema::create('cursos', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
Ahora abre el archivo database/migrations/…create_curso_estudiante_table.php que es la tabla intermedia en donde se crearán las relaciones con las tablas cursos y estudiantes:
Schema::create('curso_estudiante', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('curso_id');
$table->foreign('curso_id')->references('id')->on('cursos')->onDelete('cascade');
$table->unsignedBigInteger('estudiante_id');
$table->foreign('estudiante_id')->references('id')->on('estudiantes')->onDelete('cascade');
$table->timestamps();
});
En el anterior código el método unsignedBigInteger() asigna al campo curso_id un tipo de dato entero, positivo y soporta un valor muy grande. El método foreign() define la llave foránea y la relación entre los campos curso_id de la tabla curso_estudiante y el campo id de la tabla cursos.
Integridad referencial
Una de las principales bondades de las claves foráneas es que permiten eliminar y actualizar registros en cascada, todos los registros relacionados son eliminados de acuerdo a las relaciones de clave foránea. Una alternativa es no eliminar los registros relacionados, y poner el valor de la clave foránea a NULL.
Las opciones estándar cuando se elimina una registro con clave foránea son:
ON DELETE RESTRICT es la acción predeterminada, y no permite una eliminación si existe un registro asociado, como se mostró en el ejemplo anterior.
ON DELETE NO ACTION hace lo mismo.
ON DELETE SET DEFAULT actualmente no funciona en MySQL - se supone que pone el valor de la clave foránea al valor por omisión (DEFAULT) que se definió al momento de crear la tabla.
ON DELETE CASCADE, y una fila en la tabla padre es eliminada, entonces se eliminarán las filas de la tabla hijo cuya clave foránea sea igual al valor de la clave referenciada en la tabla padre. Esta acción siempre ha estado disponible en MySQL.
ON DELETE SET NULL, las filas en la tabla hijo son actualizadas automáticamente poniendo en las columnas de la clave foránea el valor NULL. Si se especifica una acción SET NULL, debemos asegurarnos de no declarar las columnas en la tabla como NOT NULL.
Relacionar los modelos Estudiante y Curso
Toca crear las relaciones entre Estudiante y Curso a nivel de modelo, para ello abre el archivo app/Models/Estudiante.php y como un estudiante puede tener muchos cursos se usa el método en plural y se utiliza belongsToMany().
belongsToMany--pertenece a muchos--
Un estudiante pertenece a muchos cursos
Agrega la función estudiantes() al archivo:
//Relationships Many to Many
public function cursos(){
return $this->belongsToMany(Curso::class, 'curso_estudiante');
}
Para terminar de crear la relación a nivel modelo abre el archivo app/Models/Curso.php y como un curso puede pertenecer a muchos estudiantes el nombre del método debe estar en plural y al igual que el método anterior se usa belongsToMany():
//Relationships Many to Many
public function estudiantes(){
return $this->belongsToMany(Estudiante::class, 'curso_estudiante');
}
Agregar datos de prueba
Para generar datos falsos de prueba voy a usar Factories para poblar las tablas de la base de datos, para crear el factory para el modelo Estudiante ejecuta la siguiente instrucción en la consola de comandos:
php artisan make:factory EstudianteFactory
Ahora para crear el factory para el modelo Curso:
php artisan make:factory CursoFactory
Configurar EstudianteFactory
Abre el archivo database/factories/EstudianteFactory.php y para agregar información falsa de prueba vas utilizar la librería Faker de Laravel para lo cual pega el siguiente código en tu archivo:
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
/** @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Estudiante>*/
class EstudianteFactory extends Factory
{
/*** Define the model's default state.*
* @return array<string, mixed>*/
public function definition()
{
return [
'name' => $this->faker->name(),
'last_name' => $this->faker->lastName(),
];
}}
ManyToMany
Se utiliza una relación ManyToMany cuando ambos modelos pueden relacionarse con varios modelos del otro lado de la relación. Piense en varias etiquetas que puedan relacionarse con varias publicaciones, pero también al revés.
Para que esta relación funcione, debe haber una tabla dinámica adicional que contenga claves externas para ambas tablas de modelos. El nombre de esta tabla debe ser una combinación alfabética de las dos tablas relacionadas en plural. En este ejemplo, el nombre de la tabla sería post_tag y los campos de clave externa post_id y tag_id.
En el modelo Tag, la relación se define así:
public function posts()
{
return $this->belongsToMany(Post::class);
}
Mientras que en el modelo Post la relación se define así:
public function tags()
{
return $this->belongsToMany(Tag::class);
}
Puede asociar y desasociar los modelos entre sí de esta manera:
// On the post model
$post->tags()->attach($post);
$post->tags()->detach($post);
$post->tags()->sync([1,2,3]);
// On the tag model
$tag->posts()->attach($tag);
$tag->posts()->detach($tag);
$tag->posts()->sync([1,2,3]);
O puede sincronizar todos los modelos con relaciones, esto sobrescribirá todos los modelos relacionados en el modelo específico.
// On the post model
$post->tags()->sync([1,2,3]);
// On the tag model
$tag->posts()->sync([1,2,3]);
Los modelos con relaciones se pueden recuperar así:
$post->tags
Cuando llame al método de relación, obtendrá un objeto HasMany que también es un generador (de consultas).
// Collection of published Post models related to $tag.$tag->posts()->where('published', true)->get();
bibliografia::
https://diarioprogramador.com/laravel-relaciones-muchos-a-muchos-many-to-many/
https://styde.net/pivot-tables-con-eloquent-en-laravel/
https://blog.pleets.org/article/relacion-muchos-a-muchos-eloquent
https://desarrolloweb.com/articulos/migraciones-laravel.html
https://codea.app/blog/sistema-de-tags
https://bluuweb.github.io/tutorial-laravel/db-relacional/#restricciones-base-de-datos
====================================
https://norvicsoftware.com/eloquent-orm-en-laravel-8/
https://norvicsoftware.com/migraciones-en-laravel-8/
https://styde.net/laravel-6-doc-eloquent-relaciones/
https://imoralescs.gitbooks.io/laravel/content/base-de-datos-y-migraciones-migrations.html
https://norvicsoftware.com/migraciones-en-laravel-8/
Comentarios
Publicar un comentario