Modelos

icon picker
Polimorfismo ?????????

La relación 1:1 o 1:n

Las principales relaciones que ofrece Eloquent:
hasMany y pertenecen a Muchos .
la relación hasOne es simplemente hasMany limitada a un solo registro y no se usa mucho.
image.png
Nosotros a tiene una b ( hasOne ) o a tiene varias b ( hasMany ).
Lo contrario: b es propiedad de a ( pertenece a ).

La relación n:n


image.png
Tenemos a pertenece a uno o más b ( pertenecen a muchos ).
Y tenemos que b pertenece a uno o más a ( perteneceaMuchos ).

Relación de una tabla a varias tablas

Tipo de relación 1:n

Ahora imagina esta situación:
image.png
La tabla c se puede relacionar con la tabla a o con la tabla b . En esta situación, ¿cómo administrar una clave externa en la tabla c? ¿Cómo llamarlo y cómo saber con qué tabla está en relación?
Podemos ver claramente que necesitaremos otro dato: seguramente conocer la tabla en relación .
Como necesitamos dos piezas de información, necesitamos dos columnas:
image.png
Entonces tenemos dos columnas:
relatable_id : la clave externa que almacena la identificación del registro relacionado
relatable_type : la clase del modelo relacionable.
Aquí está la figura completa con los nombres de estas relaciones:
image.png
morphOne : es el hasOne pero de varias tablas.
morphMany : es el hasMany pero de varias tablas.
morphTo : pertenece a pero destinado a varias tablas.

Tipo de relación n:n

Podemos tener el mismo razonamiento para una relación n:n con varias tablas en un lado de la relación:
image.png
morphToMany : este es el pertenecen a muchos pero de varias tablas.
morphedByMany : este es el pertenecen a muchos pero en la dirección de varias tablas.

Los datos

Vamos a ver un ejemplo de la gestión de películas introduciendo el polimorfismo. Hasta entonces teníamos categorías y películas, vamos a agregar actores, ¡todavía es bastante relevante para las películas! Un actor puede actuar en varias películas y una película tiene varios actores, así que de nuevo tenemos una relación n:n . Obviamente, podríamos usar una segunda tabla dinámica, pero será más elegante con solo una y polimorfismo.

Migraciones

Nada cambia en la migración de categorías y películas. Eliminamos la tabla dinámica que habíamos creado. Y creamos una migración para nuestra nueva tabla dinámica:
php artisan make:migration filmables
image.png
Y vamos a proporcionar este código:
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class Filmables extends Migration
{
public function up()
{
Schema::create('filmables', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->foreignId('film_id')
->constrained()
->onDelete('cascade')
->onUpdate('cascade');
$table->morphs('filmable');
});
}

public function down()
{
Schema::dropIfExists('filmables');
}
}

El método morphs es útil porque crea automáticamente las dos columnas para la relación polimórfica.
También necesitamos una migración y un modelo para los actores:
php ar
image.png
/


Con este código:
Schema::create ( 'actores' , función ( Blueprint $tabla ) {
$tabla- > id () ;
$tabla- > cadena ( 'nombre' ) -> único () ;
$tabla- > cadena ( 'slug' ) -> único () ;
$tabla -> marcas de tiempo () ;
}) ;
Solo proporcionamos un nombre y un slug, en cuanto a las categorías.
Regeneramos las tablas:
php artesanal migrar:fresco
Si todo va bien, deberíamos tener las 4 tablas que nos interesan:

image.png

Las relaciones

Categoría

Para el modelo Categoría se proporciona esta relación (que reemplaza a la anterior):
protected $fillable = [ 'name' , 'slug' ] ;
películas de función pública ()
{
return $ this- > morphToMany ( Film :: class , 'filmable' ) ;
}

Actor

Será lo mismo para el modelo Actor :
películas de función pública ()
{
return $ this- > morphToMany ( Film :: class , 'filmable' ) ;
}

Película

Para el modelo Film , se proporcionan estas dos relaciones:
categorías de función pública ()
{
return $ this- > morphedByMany ( Categoría :: clase , 'filmable' ) ;
}
actores de la función pública ()
{
return $ this- > morphedByMany ( Actor :: class , 'filmable' ) ;
}

La población

Llenaremos las tablas para nuestras pruebas.
Necesitaremos una fábrica para los actores:
php artesanal hacer: fábrica ActorFactory
image.png
Con este código:
< ?php
espacio de nombres Base de datos\Fábricas;
use App\Models\Actor;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Soporte\Str;
clase ActorFactory extiende Factory
{
protegido $modelo = Actor :: clase ;
definición de función pública ()
{
$nombre = $esto -> farsante -> nombre () ;
volver [
'nombre' = > $nombre,
'slug' = > Str::slug ( $nombre ) ,
] ;
}
}
Todo lo que queda es modificar el código de DatabaseSeeder :
< ?php
espacio de nombres Base de datos\Sembradores;
use Illuminate\Database\Seeder;
use App\Models\ { Película, Categoría, Actor } ;
use Illuminate\Soporte\Str;
clase DatabaseSeeder extiende Seeder
{
/**
* Sembrar la base de datos de la aplicación.
*
* @retorno nulo
*/
ejecución de función pública ()
{
Actor::factory () -> contar ( 10)->crear () ;
$categorias = [
'Comedia' ,
'drama' ,
Want to print your doc?
This is not the way.
Try clicking the ⋯ next to your doc name or using a keyboard shortcut (
CtrlP
) instead.