5.13 Relaciones Uno a Muchos en Laravel
5.13.1 Introducción
En el tema anterior aprendimos a crear una relación uno a uno entre un modelo User y un modelo Phone. Cada usuario tenía un único teléfono asociado.
Sin embargo, en muchos casos reales esto no es suficiente. Por ejemplo:
- Un usuario puede tener varios teléfonos: personal, trabajo, casa.
- Un cliente puede tener varios pedidos.
- Un autor puede escribir muchos artículos.
Para cubrir estos casos, Laravel permite definir relaciones uno a muchos.
Comparativa Visual
erDiagram
User ||--o{ Phone : has
User {
int id
string name
}
Phone {
int id
int user_id
string prefix
string number
}
Diferencia clave
En una relación uno a muchos:
- Un usuario puede tener muchos teléfonos.
- Cada teléfono pertenece a un solo usuario.
Este tema se basa en el código del tema anterior. Iremos modificando progresivamente el proyecto.
5.13.2 Actualizar los Modelos
Antes de comenzar, vamos a eliminar los datos que creamos en la base de datos para poder modificar los seedersy volver a ejecutarlos.
5.13.2.1 En el modelo User
Sustituimos hasOne por hasMany:
Relación actualizada en User.php
5.13.2.2 En el modelo Phone
belongsTo se mantiene igual:
5.13.3 Modificar Seeder
En UserSeeder.php, En este caso vamos a crear dos usuarios adminy NoPhone:
Seeder con varios teléfonos
Ahora vamos a modificar el PhoneSeeder.php para crear varios teléfonos,los telefonos selos asginamos todas a admin para utilizar la realción uno a muchos:
Seeder con varios teléfonos
Ahora volvemos a generar las tablas con las migraciones y los datos de prueba:
Perfecto, ya lo tenesmos todo lista para poder utilizar las relaciones uno a muchos. Para ello vamos a modificar los controladores y las vistas.
5.13.4 Vista Web
5.13.4.1 Controlador
En UserController@index, cargamos los teléfonos:
A simple vista, el método index no cambia mucho. La diferencia es que ahora estamos cargando una colección de teléfonos para cada usuario. Ahora usuuario me devuelve un objeto hasMany y no un objeto hasOne.
Controlador web UserController
5.13.4.2 Vista
Modificamos las dos vistas, la que muestra todos los usuarios con sus teléfonos y el detalle de un usuario.
Vista con teléfonos en bucle
Y la modificación del detalle de un usuario:
Vista detalle de usuario con teléfonos
5.13.5 API con Relación Uno a Muchos
5.13.5.1 Controlador API
Modificamos el modelo, ahora será whith('phones') para cargar los teléfonos de cada usuario.
API UserController\@index
5.13.5.2 Resource
También modificamos el UserResource para devolver un array de teléfonos. En este caso, la relación phones devuelve una colección de objetos Phone, por lo que debemos mapearla a un array.
UserResource con array de teléfonos
5.13.6 Comparativa final con Uno a Uno
| Elemento | Uno a Uno | Uno a Muchos |
|---|---|---|
| Relación User | hasOne(Phone::class) |
hasMany(Phone::class) |
| Vista Blade | $user->phone |
$user->phones as $phone |
| JSON API | telefono objeto |
phones[] array de objetos |
| Seeder | 1 teléfono por user | varios teléfonos por user |
5.13.7 Ejercicio Final: Varias Direcciones
Objetivo: Modificar el ejercicio del tema anterior para que un usuario pueda tener múltiples direcciones.
Pasos sugeridos:
-
Verifica que la tabla
addressestiene la claveuser_id. -
Cambia en el modelo
User:
-
En el modelo
Address, asegúrate de tenerbelongsTo(User::class). -
En el seeder, genera varias direcciones por usuario.
-
En la vista, muestra la lista de direcciones para cada usuario.
-
En el API, actualiza el
UserResourcepara devolveraddresses.