<<<<<<< HEAD
Episodio 8 - Relaciones
Laravel 11
Pequeña actualización para Laravel 11, puesto que no trae el Api por defecto.
- Ejecutar en la terminal
︎php artisan install:api
- Añadir en el archivo User.php︎
- use Laravel\Sanctum\HasApiTokens;
- La primera línea después del primer { dejar así︎
- use HasFactory, Notifiable, HasApiTokens;
=======
8 - Relaciones. 1:1 / 1:N / N:M ...
>>>>>>> fe5a53abf9e80cf3b3ffe1698ffe71292e7f9bd8
Apartados/tiempos:
<<<<<<< HEAD 0:04:08 - Relación 1 A 1 0:26:57 - Usando Relaciones En Vistas 0:33:26 - Usando Relaciones En Api 0:40:17 - Relación 1 A Muchos / Muchos A 1 0:47:24 - Relación Muchos A Muchos Y Pivotes 1:10:46 - Relación 1 A 1 Indirecta O Con Modelo De Paso 1:19:15 - Relación 1 A Muchos Con Modelo De Paso (Through) 1:22:31 - Relación Polimórfica 1 A 1 1:36:38 - Relación Polimórfica 1 A Muchos / Muchos A 1 1:40:18 - Relación Polimórfica Muchos A Muchos 1:57:04 - Conclusiones ======= * 0:04:08 - Relación 1 A 1 * 0:26:57 - Usando Relaciones En Vistas * 0:33:26 - Usando Relaciones En Api * 0:40:17 - Relación 1 A Muchos / Muchos A 1 * 0:47:24 - Relación Muchos A Muchos Y Pivotes * 1:10:46 - Relación 1 A 1 Indirecta O Con Modelo De Paso * 1:19:15 - Relación 1 A Muchos Con Modelo De Paso (Through) * 1:22:31 - Relación Polimórfica 1 A 1 * 1:36:38 - Relación Polimórfica 1 A Muchos / Muchos A 1 * 1:40:18 - Relación Polimórfica Muchos A Muchos * 1:57:04 - Conclusiones
fe5a53abf9e80cf3b3ffe1698ffe71292e7f9bd8
Introducción
Las relaciones entre modelos se usan para saber en si un modelo está conectado a otro y para realizar acciones entre ellos.
Hasta ahora hemos creado modelos independientes, lo que NO es lo habitual
¿Cómo lo transladamos a las migraciones?
<<<<<<< HEAD
Relación 1-1
=======
Relación 1-1 hasOne
fe5a53abf9e80cf3b3ffe1698ffe71292e7f9bd8
En la relación 1-1
(User posee un Phone y Phone posee la id de User) uno de los elementos debe poseer al otro y ese otro debe poseer la id del primero. En este caso:
- Creamos un modelo Phone con su migración
php artisan make:model Phone -m
- En la migración de Phone hay que añadir lo siguiente:
public function up(): void
{
Schema::create('phones', function (Blueprint $table) {
$table->id();
$table->unsignedInteger('prefix');
$table->unsignedBigInteger('phone_number');
$table->unsignedBigInteger('user_id');
$table->timestamps();
});
}
<<<<<<< HEAD - En el modelo, vamos a declarar el array guard como vacío para indicar que todos los datos son editables - En el CONTROLADOR de User se le dice al usuario que un User posee un Phone. - Para ello se crea una función HasOne (tiene) - Esta nomenclatura de POSEE/TIENE y de PERTENECE es importante tenerla muy clara, ya que es lo que vamos a implementar en código ======= - En el modelo, vamos a declarar el array guard como vacío para indicar que todos los datos son editables -
¿Qué modelo tiene la clave foránea?
Como hemos visto, es el modelo Phone el que contiene el user_id
Por lo tanto y esto suele generar confusiones al principio:
Vamos a decir que
EL USUARIO TIENE UN TELÉFONO
EL TELÉFONO PERTENECE a un usuario
Asi,
Modelo User. Lógica
- En el modelo User se le dice al usuario que un User posee un Phone.
- Para ello se crea una función HasOne (tiene)
- Esta nomenclatura de POSEE/TIENE y de PERTENECE es importante tenerla muy clara, ya que es lo que vamos a implementar en código
- La convención es que sea el nombre del modelo en minúscula, va a devolver un HasOne
- Aquí vamos a construir la devolución de todos los datos del usuario
- Como hemos usado la convención de nombres, podemos hacerlo de forma más simple. Ya que nuestro modelo incluye un user_id
- Si no lo respetamos, le tenemos que decirle qué nombre tiene la clase foránea, y el id de mi modelo es el ..
fe5a53abf9e80cf3b3ffe1698ffe71292e7f9bd8
- Si no lo respetamos, le tenemos que decirle qué nombre tiene la clase foránea, y el id de mi modelo es el ..
public function phone(): HasOne
{
<<<<<<< HEAD
return $this->hasOne(Phone::class /*, 'user_id', 'id' //Si no se respeta la nomenclatura de nombres, Laravel no sabe a qué clave se refiere*/);
}
- En el modelo de Phone se le dice al usuario que un Phone pertenece a un User.
public function phone(): HasOne
{
return $this->hasOne(Phone::class /*, 'user_id', 'id' //Si no se respeta la nomenclatura de nombres, Laravel no sabe a qué clave se refiere*/);
}
Usando Relaciones En Vistas
======= return $this->hasOne(Phone::class ); //Si no se respeta la nomenclatura de nombres, Laravel no sabe a qué clave se refiere habría que ponerlo de la siguiente manera //return $this->hasOne(Phone::class, 'user_id', 'id' ); }
#### Modelo Phone. Lógica
- En el **modelo** de Phone hacemos una función llamado user
- El que NO tiene la clave foránea, **PERTENECE** a..
- se le dice al usuario que un Phone pertenece a un User.
```php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Phone extends Model
{
//
protected $guarded = [];//para que no se proteja ningun campo
public function user():BelongsTo
{
return $this->belongsTo(User::class);
}
}
Ya hemos completado la relación 1-1
Seeders
Para tener datos de prueba, vamos a generarnos unos seeders en este paso, aunque no se haga uso de factorias (se comentará la factoria que viene por defecto):
php artisan make:seeder UserSeeder
php artisan make:seeder PhoneSeeder
seeder/factory/faker
Se ve en profundidad en la clase 7
En el archivo DatabaseSeeder.php pricipal, en la llamada run le decimos que vamos a hacer uso de ellos para lo que el archivo se queda así:
<?php
namespace Database\Seeders;
use App\Models\User;
// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*/
public function run(): void
{
// User::factory(10)->create();
/*
User::factory()->create([
'name' => 'Test User',
'email' => 'test@example.com',
]);*/
$this->call([
PhoneSeeder::class,
UserSeeder::class
]);
}
}
Nos vamos al seeder del usuario para crear unos datos de prueba:
UserSeeder.php
Vamos a generar algunos usuarios definiendo incluso su ID de la siguiente forma dentro de su UserSeeder:
Añado el modelo: use App\Models\User;
Dentro de la función run, creo un usuario:
User::create([
'id' => 1,
'name' => 'example',
'email' => 'example@example.com',
'password' => Hash::make('122345678')
]);
PhoneSeeder.php
Añado elmodelo use App\Models\Phone;
Igualmente, dentro de la función run(), incluyo la creación de un usuario:
Phone::create([
'prefix' => 34,
'phone_number' => '123456789',
'user_id' => 1
]);
db:seed -> Poblar la base de datos
De esta forma tenemos ya nuestra base de datos relacional creada, y vamos a poblarla ahora:
php artisan db:seed
- INFO Seeding database.
Usando Relaciones En Vistas
Vamos ahora a recuperar esa información y visualizarla.
- Este funcionamieto, tando en Vistas como en API es el mismo para todas las relaciones, 1:N, N:M, etc..
fe5a53abf9e80cf3b3ffe1698ffe71292e7f9bd8
Para mostrar los datos en las vistas necesitaremos hacer uso de los controllers.
- Creamos el UserController con el comando:
php artisan make:controller UserController
<<<<<<< HEAD 2. Dentro del UserController importamos al usuario y creamos la función index: ======= 2. Dentro del UserController importamos al usuario y creamos la función index donde vamos a buscar a nuestro usuario mediante la función find 1. buscamos el id 1 2. y le pasamos la información a la vista con los datos de usuario 3. Fijarse que aquí no estamos buscando los datos relacionados, eso ya se ha hecho en el modelo, y tendremos acceso a ellos de forma directa.
fe5a53abf9e80cf3b3ffe1698ffe71292e7f9bd8
use App\Models\User;
public function index()
{
$user = User::find(1);
return view('index', compact('user'));
}
<<<<<<< HEAD
3. Para especificar que el contenido va a salir por algún sitio especificamos la ruta en routes/web
importando el User Controller y cambiando la función get para decirle que el contenido que se va a mostrar proviene de la clase index del UserController:
=======
3. Para especificar que el contenido va a salir por algún sitio especificamos la ruta en routes/web
importando el User Controller y cambiando la función get para decirle que el contenido que se va a mostrar proviene del método index del UserController:
fe5a53abf9e80cf3b3ffe1698ffe71292e7f9bd8
use App\Http\Controllers\UserController;
Route::get('/', [UserController::class, 'index'])->name('index');
<<<<<<< HEAD
4. Finalmente, en nuestras vistas creamos el archivo index.blade.php
que mostrará nuestra vista y le añadimos dentro del body de la estructura HTML:
<h1>{{ $user->phone->prefix }}</h1>
<h1>{{ $user->phone->phone_number }}</h1>
Usando Relaciones En Api
=======
4. Finalmente, en nuestras vistas creamos el archivo index.blade.php
que mostrará nuestra vista y le añadimos dentro del body de la estructura HTML
1. Observa que accedemos a los datos relacionados a través de la FUNCIÓN phone:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Relaciones</title>
</head>
<body>
<h1>{{ $user->name }}</h1>
<h1>{{ $user->email }}</h1>
<h2>Datos relacionados a través de foreign key</h2>
<h3>{{ $user->phone->prefix }} / {{ $user->phone->phone_number }}</h3>
</body>
</html>
Y ya podemos arrancar el servicio.
Usando Relaciones En Api
Laravel 11
Pequeña actualización para Laravel 11, puesto que no trae el Api por defecto.
- Ejecutar en la terminal
︎php artisan install:api
- Añadir en el archivo User.php︎
- use Laravel\Sanctum\HasApiTokens;
- La primera línea después del primer { dejar así︎
- use HasFactory, Notifiable, HasApiTokens;
fe5a53abf9e80cf3b3ffe1698ffe71292e7f9bd8
Para mostrar los datos en la API necesitaremos hacer uso de las resources.
- Para ello creamos la UserResource con el comando:
php artisan make:resource UserResource
- Después en la UserResource añadiremos lo siguiente en lugar del return que ya había:
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
<<<<<<< HEAD
=======
//le vamos a dar un poco de formato al teléfono
>>>>>>> fe5a53abf9e80cf3b3ffe1698ffe71292e7f9bd8
'phone' => '(' . $this->phone->prefix . ')' . $this->phone->phone_number,
];
- Y finalmente añadimos la ruta en
routes/api
:
Route::get('/user', function (Request $request) {
$user = User::find(1);
return new UserResource($user);
});
<<<<<<< HEAD
Relación 1 A Muchos / Muchos A 1
Una relación 1 a muchos se da cuando un elemento X posee muchos elementos Y pero esos elementos Y sólo son poseídos por un único elemento X. Un usuario tiene varios teléfonos y esos teléfonos son de ese usuario, no pertenecen a nadie más.
- Primero se modifican los modelos y se le añade:
public function phones(): HasMany
{
return $this->hasMany(Phone::class /*, 'user_id', 'id' //Si no se respeta la nomenclatura de nombres, Laravel no sabe a qué clave se refiere*/);
}
- Deberemos crear datos para poder testear y para ello, usamos los seeders:
php artisan make:seeder UserSeeder
php artisan make:seeder PhoneSeeder
php artisan make:seeder PhoneSeeder
Probamos también la API
Levantamos el servicio y acudimos a nuestro Software para realizar peticiones API, en este caso la extensión Thunder Client para probar esa ruta:
Relación 1:N hasMany (1 a muchos / muchos a 1)
Para esta parte, vamos a utilizar el mismo ejemplo.
Una relación 1 a muchos se da cuando un elemento X posee muchos elementos Y pero esos elementos Y sólo son poseídos por un único elemento X.
Ahora, vamos a cambiar las reglas para decir que, un usuario TIENE varios teléfonos y esos teléfonos SON de ese usuario, no pertenecen a nadie más.
- Primero se modifican los modelos y se le añade (Comenta y añade, mejor que eliminar, para ver el progreso):
- En la base de datos no se va a hacer cambios, pero vamos a modificar el MODELO
- En primer lugar, por convención, la función ahora es plural ya que se va a devolver más de uno:
- Importará la librería
use Illuminate\Database\Eloquent\Relations\HasMany;
Modelo Phone
public function phones(): HasMany
{
//1 - 1
// return $this->hasOne(Phone::class );
//Si no se respeta la nomenclatura de nombres, Laravel no sabe a qué clave se refiere habría que ponerlo de la siguiente manera
//return $this->hasOne(Phone::class, 'user_id', 'id' );
//1 - n
return $this->hasMany(Phone::class );
//Si no se respeta la nomenclatura de nombres, Laravel no sabe a qué clave se refiere*/
//return $this->hasMany(Phone::class /*, 'user_id', 'id' );
}
- Deberemos crear datos para poder testear varios telefonos y para ello, usamos los seeders
PhoneSeeder.php
fe5a53abf9e80cf3b3ffe1698ffe71292e7f9bd8
- Y añadimos datos a éstos para que se añadan a la base de datos como filas nuevas:
<<<<<<< HEAD
User::create([
'id' => 1,
'name' => 'example',
'email' => 'example@example.com',
'password' => Hash::make('12345678'),
]);
Phone::create([
'prefix' => 34,
'phone_number' => 66666,
'user_id' => 1,
]);
Phone::create([
'prefix' => 34,
'phone_number' => 66666,
'user_id' => 1,
]);
// Phone::create([ 'prefix' => 34, 'phone_number' => '666666', 'user_id' => 1 ]);
Phone::create([
'prefix' => 34,
'phone_number' => '777777',
'user_id' => 1
]);
```
DatabaseSeeder
Comento el seeder del User Seeder para que NO se ejecute Y ejecutamos el db seed
fe5a53abf9e80cf3b3ffe1698ffe71292e7f9bd8
php artisan db:seed
[!NOTE] Para que, al hacer seed, no se vuelvan a crear de nuevo, comentamos el siguiente código:
- Del archivo
database/seeders/PhoneSeeder
:
Phone::create([ 'prefix' => 34, 'phone_number' => 66666, 'user_id' => 1, ]);
- Del archivo
database/seeders/DatabaseSeeder
:
UserSeeder::class,
Y volvemos a hacer:
php artisan db:seed
- Añadimos al archivo
PhoneSeeder
un nuevo phone y le hacemos el seed para que lo añada a la base de datos y seguidamente descomentamos el código anteriormente comentado:
Phone::create([ 'prefix' => 33, 'phone_number' => 77777, 'user_id' => 1, ]);
<<<<<<< HEAD 5. En
ìndex.blade
comentamos elcódigo dentro del body y escribimos: ======= 5. Enìndex.blade
comentamos elcódigo dentro del body y escribimos para que se muestren todos los teléfonos:fe5a53abf9e80cf3b3ffe1698ffe71292e7f9bd8
```
{{ $user->name }} Phones:
@foreach ($user->phones as $phone)
<ul>
<li>{{ $phone->prefix }} {{ $phone->phone_number }}</li>
</ul>
@endforeach
``
<<<<<<< HEAD
6. Y finalmente en
UserResourcesobreescribimos phone para que muestre los datos de todos los teléfonos:
=======

* Y finalmente, para el caso de la API, en
UserResource` sobreescribimos phone para que muestre los datos de todos los teléfonos:
fe5a53abf9e80cf3b3ffe1698ffe71292e7f9bd8
'phones' => $this->phones
<<<<<<< HEAD
Relación Muchos A Muchos
Una relación muchos a muchos se da cuando, por ejemplo, un elemento X posee muchos elementos Y y un elemento Y es poseído por muchos elementos X. Varios usuarios tienen roles específicos pero cada rol lo poseen varios usuarios.
Relación Muchos A Muchos (enlace)
Esta si tiene ciertas particularidades con las anteriores, ya no hay un elemento único en una de las partes de la relación
- Podemos recordar este tipo de relación relacional en diferente documentación como esta enlazada aquí
Una relación muchos a muchos se da cuando, por ejemplo, un elemento X posee muchos elementos Y y un elemento Y es poseído por muchos elementos X.
* Varios usuarios tienen roles específicos pero cada rol lo poseen varios usuarios.
Modelo Role
fe5a53abf9e80cf3b3ffe1698ffe71292e7f9bd8
Creamos un modelo
Role
con su migración:
php artisan make:model Role --migration
<<<<<<< HEAD Y le añadimos un atributo
name
para hacer pruebas, cambiándole e el modelo el atributoprotected $guarder = []
.Para relacionar de muchos a muchos necesitamos una tabla pivote para saber que roles están asociados a qué usuario:
php artisan make:migration create_role_user_table
Editamos el archivo de migración pivote que hemos creado y le añadimos:
Y le añadimos a la migración un atributo
name
de tipo string para hacer pruebas, ($table->string('name');
) cambiándole e el modelo el atributoprotected $guarded = [];
Migramos
Para relacionar de muchos a muchos necesitamos una tabla pivote para saber que roles están asociados a qué usuario
- Es importante mantener la CONVENCIÓN de nomenclaturas para después poder mantenerlo de forma más fácil sin aportar información extra
- nombremodelo1_nombremodelo2
- role_user
- En singular y ordenados alfabéticamente con barra baja
php artisan make:migration create_role_user_table
- ...relationships\database\migrations/2025_01_25_065858_create_role_user_table.php] created successfully.
- Esta es una migración pura sin modelo asociado.
- Así sabemos qué roles están asociados a qué usuarios
![]()
create_role_user
Editamos el archivo de migración pivote que hemos creado: * La información mínima es el id de cada tabla relacionada * pero aquí podríamos incluir, por ejemplo en un carrito de compra, a qué precio compró en ese momento, qué cantidad de esa compra, etc, ya que en muchas ocasiones esto nos interesará. * nosotros vamos a añadir el campo added_by, para añadir quién añadió el role
fe5a53abf9e80cf3b3ffe1698ffe71292e7f9bd8
$table->unsignedBigInteger('role_id'); $table->unsignedBigInteger('user_id'); $table->string('added_by')->nullable(); //Opcional
<<<<<<< HEAD Y migramos.
Añadimos datos a la tabla
Role
y para ello creamos un seeder, el cuál añadimos a nuestroDatabaseSeeder
y dentro del cuál creamos varios roles. Añadimos una estructura para no tener que tocar varios seeders y, en elRoleSeeder
creamos la tabla que hace referencia a tanto rol como usuario para crear la relación(creamos varios de estos para ver la relación de muchos a muchos):Y migramos.
Seeders..
php artisan make:seeder RoleSeeder
Añadimos datos a la tabla Role
y para ello creamos un seeder, el cuál añadimos a nuestro DatabaseSeeder
y dentro del cuál creamos varios roles.
$this->call([
PhoneSeeder::class,
UserSeeder::class,
RoleSeeder::class,
]);
Y en el RoleSeeder.php incluimos 4 roles diferentes, quedando la clase así (recuerda importar la librería del modelo Role):
php
class RoleSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
Role::create([
'id' => 1,
'name' => 'admin'
]);
Role::create([
'id' => 2,
'name' => 'staff'
]);
Role::create([
'id' => 3,
'name' => 'user'
]);
Role::create([
'id' => 4,
'name' => 'guest'
]);
}
}
Ahora en nuestro Seeder de usuario (UserSeeder.php) vamos a crear también varios usuarios:
User::create([
'id' => 1,
'name' => 'example',
'email' => 'example@example.com',
'password' => Hash::make('122345678')
]);
User::create([
'id' => 2,
'name' => 'example2',
'email' => 'example2@example.com',
'password' => Hash::make('122345678')
]);
User::create([
'id' => 3,
'name' => 'example3',
'email' => 'example3@example.com',
'password' => Hash::make('122345678')
]);
Añadimos una estructura para no tener que tocar crear más seeders y,
en el RoleSeeder
creamos la tabla que hace referencia a tanto rol como usuario para crear la relación (creamos varios de estos para ver la relación de muchos a muchos):
- Lo hacemos directamente a través del DB, recuerda añadir más, al menos 5 de forma personalizada
fe5a53abf9e80cf3b3ffe1698ffe71292e7f9bd8
use Illuminate\Support\Facades\DB;
<<<<<<< HEAD
DB::table('role_user')->insert([
'role_id' => 1,
'user_id' => 1,
'added_by' => 'Juan',
]);
Posteriormente, hacemos un reset de la base de datos para no duplicar contenido:
.... En la clase RoleSeeder, método run(), Tras crear los usuarios, incluimos (y completamos) ...
DB::table('role_user')->insert([ 'role_id' => 1, 'user_id' => 1, 'added_by' => 'Antonio' ]);
DB::table('role_user')->insert([
'role_id' => ,
'user_id' => ,
'added_by' => ''
]);
DB::table('role_user')->insert([
'role_id' => ,
'user_id' => ,
'added_by' => ''
]);
DB::table('role_user')->insert([
'role_id' => ,
'user_id' => ,
'added_by' => ''
]);
DB::table('role_user')->insert([
'role_id' => ,
'user_id' => ,
'added_by' => ''
]);
``` Posteriormente, hacemos un reset de la base de datos para no duplicar contenido:
fe5a53abf9e80cf3b3ffe1698ffe71292e7f9bd8
php artisan migrate:reset
php artisan migrate
php artisan db:seed
<<<<<<< HEAD Para establecer la relación, modificamos los modelos.Para el User se crea un método como el de a continuación y para el Role s crea exactamente igual pero cambiando Role::class por User::class: =======
Relaciones BelongToMany entre modelos
Para establecer la relación, modificamos los modelos Role y User.
Siempre que sea muchos amuchos, recurriremos al BelongsToMany
Para el User se crea un método como el de a continuación y para el Role s crea exactamente igual pero cambiando Role::class por User::class:
- Como siempre, si no hemos respetado la convencion debremos darle más datos para indicar tabla y FK
- Si tiene info extra, le indicamos los pivotes con withPivot..
php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
class Role extends Model
{
//
protected $guarded = [];
public function users(): BelongsToMany
{
return $this->belongsToMany(User::class)->withPivot('added_by');
}
}
fe5a53abf9e80cf3b3ffe1698ffe71292e7f9bd8
public function roles(): BelongsToMany
{
return $this->belongsToMany(Role::class)->withPivot('added_by');
}
<<<<<<< HEAD
Vistas
fe5a53abf9e80cf3b3ffe1698ffe71292e7f9bd8 Finalmente, nos vamos a la vista del usuario que es la que se mostrará y escribimos esto para hacer una prueba:
<h1>{{ $user->name }} Roles:</h1>
@foreach ($user->roles as $role)
<ul>
<li>{{ $role->name }} Added by: {{ $role->pivot->added_by }}</li>
</ul>
@endforeach
<<<<<<< HEAD
Para la API igual, me voy al UserResource y le incluyo 'roles' => $this->roles
Nos falta dos tipos de relaciones: las de paso, y las polimórficas
Afianza este contenido primero
Es importante afianzar el contenido anterior, ya que es la base, antes de continuar con las siguientes relaciones que son más específicas, prueba ahora a implementarla en ejemplos y/o en tu proyecto.
fe5a53abf9e80cf3b3ffe1698ffe71292e7f9bd8
Relación 1 A 1 Indirecta O Con Modelo De Paso
Una relación 1 a 1 indirecta se da cuando un elemento X posee un elemento Y el cuál posee un elemento Z pero el elemento X no tiene conexión directa con el elemento Z. Una persona posee un móvil y ese móvil posee una tarjeta Sim que la persona no puede tocar sin anter tocar el móvil.
- Creamos el modelo Sim con su migration.
- Creamos las relaciones, para ello creamos la siguiente función en el modelo de
Sim
y la misma función pero cambiando Phone::class por Sim::class en el modelo dePhone
:
public function phone(): BelongsTo
{
return $this->belongsTo(Phone::class);
}
- Le decimos a la migration de
Sim
que posee:
$table->string('serial_number');
$table->string('company');
$table->unsignedBigInteger('phone_id');
- Establecemos la relación de paso diciéndole a
User
que tiene una relación conSim
a través dePhone
:
public function phoneSim(): HasOneThrough
{
return $this->hasOneThrough(Sim::class, Phone::class);
}
Relación 1 A Muchos Con Modelo De Paso (Through)¡¡¡¡
Una relación 1 a muchos con modelo de paso se da cuando un elemento X posee uno o varios elemento Y el cuál posee uno o varios elementos Z pero el elemento X no tiene conexión directa con los elementos Z. Una persona posee uno o varios móviles y esos móviles posee una o varias tarjetas Sim que la persona no puede tocar sin anter tocar el móvil.
- En los modelos añadimos las funciones con las relaciones entre ellos que en vez de ser HasOneThrough son HasManyThrough en el
User
y en vez de HasOne es HasMany enPhone
.
Relación Polimórfica 1 A 1
Una relación polimórfica se da cuando en una relación entre 3 o más elementos, el elemento X que se asocia con más de 1 elemento Y puede que no sepa si va a ser parte del elemento Y1 o del Y2, por tanto no sabe si en sus propiedades debe albergar la id de Y1 o la id de Y2. En este caso, el elemento X está en medio de una relación polimórfica. Un usuario puede poseer una imagen de perfil y la imagen puede estar en un post pero no se sabe si esa imagen forma parte del usuario o del post, por tanto, no se sabe si debe llevar la id del usuario o la id del post.
- Creamos el modelo de
Post
con su migration y le añadimos los datos a su migration. - Creamos el modelo de
Image
con su migration y le añadimos los datos a su migration añadiento también dos campos para la id que se relacionará con los otros modelos y para el nombre de esta imagen.
$table->unsignedBigInteger('imageable_id');
$table->string('imageable_type');
- Añadimos al modelo
Image
la función siguiente:
public function imageable()
{
return $this->morphTo();
}