{"id":66683,"date":"2023-06-07T19:18:09","date_gmt":"2023-06-07T17:18:09","guid":{"rendered":"https:\/\/kinsta.com\/es\/?p=66683&#038;preview=true&#038;preview_id=66683"},"modified":"2025-01-17T13:50:54","modified_gmt":"2025-01-17T12:50:54","slug":"laravel-relaciones","status":"publish","type":"post","link":"https:\/\/kinsta.com\/es\/blog\/laravel-relaciones\/","title":{"rendered":"Las Relaciones de Laravel Eloquent: Una Gu\u00eda Avanzada"},"content":{"rendered":"<p>A menudo llega un momento en la vida de todo desarrollador en el que tienes que interactuar con una base de datos. Aqu\u00ed es donde Eloquent, el mapeador objeto-relacional (ORM) de Laravel, hace que el proceso de interactuar con las tablas de tu base de datos sea intuitivo y natural.<\/p>\n<p>Es vital que, como profesional, reconozcas y comprendas los seis tipos de relaciones clave que vamos a repasar.<\/p>\n<div><\/div><kinsta-auto-toc heading=\"Table of Contents\" exclude=\"last\" list-style=\"arrow\" selector=\"h2\" count-number=\"-1\"><\/kinsta-auto-toc>\n<h2>\u00bfQu\u00e9 Son las Relaciones en Eloquent?<\/h2>\n<p>Cuando trabajamos con tablas en una base de datos relacional, podemos caracterizar las relaciones como conexiones entre tablas. Esto te ayuda a organizar y estructurar los datos sin esfuerzo, lo que permite una mayor legibilidad y manejo de los datos. En la pr\u00e1ctica, existen tres tipos de relaciones en las bases de datos:<\/p>\n<ul>\n<li>uno a uno &#8211; Un registro de una tabla se asocia con uno, y s\u00f3lo uno, de otra tabla. Por ejemplo, una persona y un n\u00famero de la Seguridad Social.<\/li>\n<\/ul>\n<ul>\n<li>uno a varios &#8211; Un registro est\u00e1 asociado a varios registros de otra tabla. Por ejemplo, un escritor y sus blogs.<\/li>\n<\/ul>\n<ul>\n<li>varios-a-varios &#8211; Varios registros de una tabla est\u00e1n asociados a varios registros de otra tabla. Por ejemplo, los alumnos y los cursos en los que est\u00e1n matriculados.<\/li>\n<\/ul>\n<p>Laravel facilita la interacci\u00f3n y la gesti\u00f3n de las relaciones entre bases de datos utilizando la sintaxis orientada a objetos de Eloquent.<\/p>\n<p>Junto con estas definiciones, Laravel introduce m\u00e1s relaciones, a saber:<\/p>\n<ul>\n<li>Has Many Through<\/li>\n<li>Relaciones Polim\u00f3rficas<\/li>\n<li>Polim\u00f3rficas de Varios a Varios<\/li>\n<\/ul>\n<p>Tomemos, por ejemplo, una tienda cuyo inventario contiene diversos art\u00edculos, cada uno en su propia categor\u00eda. Por tanto, dividir la base de datos en varias tablas tiene sentido desde el punto de vista empresarial. Esto conlleva sus propios problemas, ya que no quieres consultar todas y cada una de las tablas.<\/p>\n<p>Podemos crear f\u00e1cilmente una relaci\u00f3n simple de uno a muchos en Laravel para ayudarnos, por ejemplo, cuando necesitemos consultar los productos, podemos hacerlo utilizando el modelo Producto.<\/p>\n<figure style=\"width: 1158px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/kinsta.com\/wp-content\/uploads\/2023\/05\/pasted-image-0-6.png\" alt=\"Esquema de base de datos con tres tablas y una tabla conjunta que representa una relaci\u00f3n polim\u00f3rfica\" width=\"1158\" height=\"610\"><figcaption class=\"wp-caption-text\">Esquema de base de datos con tres tablas y una tabla conjunta que representa una relaci\u00f3n polim\u00f3rfica<\/figcaption><\/figure>\n<h2>Relaci\u00f3n Uno a Uno<\/h2>\n<p>Al ser la primera relaci\u00f3n b\u00e1sica que ofrece Laravel, asocian dos tablas de forma que una fila de la primera tabla est\u00e1 correlacionada con una sola fila de la otra tabla.<\/p>\n<p>Para ver esto en acci\u00f3n, tenemos que crear dos modelos con su propia migraci\u00f3n:<\/p>\n<pre><code class=\"language-bash\">php artisan make:model Tenant \nPhp artisan make:model Rent<\/code><\/pre>\n<p>En este punto, tenemos dos modelos, uno es el \u00abTenant\u00bb (Inquilino) y el otro es su \u00bb Rent\u00bb (Alquiler).<\/p>\n<pre><code class=\"language-php\">&lt;?php\n\n<span id=\"urn:enhancement-32a96a90-cceb-4d56-aa08-46a11cb5a1d4\" class=\"textannotation\">namespace<\/span> <span id=\"urn:enhancement-c034c06e-361f-4401-b289-5dd92dda3c09\" class=\"textannotation\">App<\/span>\\Models;\nuse Illuminate\\<span id=\"urn:enhancement-5996adf6-a5b5-40e1-98e0-0708048fe5c4\" class=\"textannotation\">Database<\/span>\\Eloquent\\<span id=\"urn:enhancement-d200cbca-509c-465c-97f4-fe369e3ad293\" class=\"textannotation\">Model<\/span>;\n\nclass Tenant extends Model\n{\n    \/**\n    * Get the rent of a Tenant\n    *\/\n    public function rent() \n    {\n        return $this-&gt;hasOne(Rent::class);\n    }\n}<\/code><\/pre>\n<p>Como eloquent determina la relaci\u00f3n de clave ajena bas\u00e1ndose en el nombre del modelo padre (Inquilino en este caso), el modelo Alquiler asume que existe una clave ajena <strong>tenant_id<\/strong>.<\/p>\n<p>Podemos sobrescribirla f\u00e1cilmente como con un argumento adicional al m\u00e9todo <strong>hasOne<\/strong>:<\/p>\n<pre><code class=\"language-php\">return $this- &gt;hasOne(Rent::class, \"custom_key\");<\/code><\/pre>\n<p>Eloquent tambi\u00e9n asume que existe una coincidencia entre la clave ajena definida y la clave primaria del padre (modelo Inquilino). Por defecto, buscar\u00e1 la coincidencia de <strong>tenant_id<\/strong> con la clave <strong>id<\/strong> del registro Tenant. Podemos sobrescribir esto con un tercer argumento en el m\u00e9todo <strong>hasOne<\/strong>, de forma que coincida con otra clave:<\/p>\n<pre><code class=\"language-php\">return $this-&gt;hasOne(Rent::class, \"custom_key\", \"other_key\"); <\/code><\/pre>\n<p>Ahora que hemos definido la relaci\u00f3n uno a uno entre los modelos, podemos utilizarla f\u00e1cilmente, as\u00ed:<\/p>\n<pre><code class=\"language-php\">$rent = Tenant::find(10)-&gt;rent;<\/code><\/pre>\n<p>Con esta l\u00ednea de c\u00f3digo, obtenemos el alquiler del inquilino con el id 10 si existe.<\/p>\n<h2>Relaci\u00f3n Uno a Varios<\/h2>\n<p>Al igual que la relaci\u00f3n anterior, \u00e9sta definir\u00e1 relaciones entre un modelo monoparental y varios modelos hijos. Es poco probable que nuestro Inquilino tenga s\u00f3lo una factura de Alquiler porque es un pago recurrente, por lo tanto, tendr\u00e1 m\u00faltiples pagos.<\/p>\n<p>En este caso, nuestra relaci\u00f3n anterior tiene defectos, y podemos solucionarlos:<\/p>\n<pre><code class=\"language-php\">&lt;?php\n\n<span id=\"urn:enhancement-239b2286-5c9a-4488-82c8-0caafdc91792\" class=\"textannotation\">namespace<\/span> <span id=\"urn:enhancement-3eb0b762-e80d-4e93-8328-4927ea89398a\" class=\"textannotation\">App<\/span>\\Models;\nuse Illuminate\\<span id=\"urn:enhancement-a6e46b67-01f6-4c2c-b6cc-b85009597cad\" class=\"textannotation\">Database<\/span>\\Eloquent\\<span id=\"urn:enhancement-1c7ef2a1-0ed8-4c72-ae0d-6dfa8216a9b4\" class=\"textannotation\">Model<\/span>;\n\nclass Tenant extends Model\n{\n    \/**\n    * Get the rents of a Tenant\n    *\/\n    public function rent() \n    {\n        return $this-&gt;hasMany(Rent::class);\n    }\n}<\/code><\/pre>\n<p>Antes de llamar al m\u00e9todo para obtener los alquileres, conviene saber que las relaciones sirven como constructores de consultas, por lo que podemos a\u00f1adir m\u00e1s restricciones (como alquiler entre fechas, pago m\u00ednimo, etc.) y encadenarlas para obtener nuestro resultado deseado:<\/p>\n<pre><code class=\"language-php\">$rents = Tenant::find(10)-&gt;rent()-&gt;where('payment', '&gt;', 500)-&gt;first();<\/code><\/pre>\n<p>Y como en la relaci\u00f3n anterior, podemos sobrescribir las claves for\u00e1neas y locales pasando argumentos adicionales:<\/p>\n<pre><code class=\"language-php\">return $this-&gt;hasMany(Rent::class, \"foreign_key\");<\/code><\/pre>\n<pre><code class=\"language-php\">return $this-&gt;hasMany(Rent::class, \"foreign_key\", \"local_key\");<\/code><\/pre>\n<p>Ahora tenemos todos los alquileres de un inquilino, pero \u00bfqu\u00e9 hacemos cuando conocemos el alquiler y queremos averiguar a qui\u00e9n pertenece? Podemos hacer uso de la propiedad <strong>belongsTo<\/strong>:<\/p>\n<pre><code class=\"language-php\">&lt;?php\n\n<span id=\"urn:enhancement-d9d7d384-713e-4aa0-b0c1-b3a3650f6c7d\" class=\"textannotation\">namespace<\/span> <span id=\"urn:enhancement-14a2dd36-b08c-4d53-a78e-21e6a5c82782\" class=\"textannotation\">App<\/span>\\Models;\nuse Illuminate\\<span id=\"urn:enhancement-53e7406b-1ab1-44aa-92f1-73bdaf2768d3\" class=\"textannotation\">Database<\/span>\\Eloquent\\<span id=\"urn:enhancement-2f5d9af6-4c22-494b-95a7-0291abb2c636\" class=\"textannotation\">Model<\/span>;\n\nclass Rent extends Model\n{\n    \/**\n    * Return the tenant for the rent\n    *\/\n    public function tenant() \n    {\n        return $this-&gt;belongsTo(Tenant::class);\n    }\n}<\/code><\/pre>\n<p>Y ahora podemos obtener el inquilino f\u00e1cilmente:<\/p>\n<pre><code class=\"language-php\">$tenant = Rent::find(1)-&gt;tenant;<\/code><\/pre>\n<p>Para el m\u00e9todo <strong>belongsTo<\/strong>, tambi\u00e9n podemos sobrescribir las claves for\u00e1neas y locales como hicimos antes.<\/p>\n<h2>Relaci\u00f3n Has-One-Of-Many<\/h2>\n<p>Como nuestro modelo de Inquilino puede estar asociado a muchos modelos de Alquiler, queremos recuperar f\u00e1cilmente el modelo relacionado m\u00e1s reciente o m\u00e1s antiguo de las relaciones.<\/p>\n<p>Una forma c\u00f3moda de hacerlo es combinar los m\u00e9todos <strong>hasOne<\/strong> y <strong>ofMany<\/strong>:<\/p>\n<pre><code class=\"language-php\">public function latestRent() {\n    return $this-&gt;hasOne(Rent::class)-&gt;latestOfMany();\n}\n\npublic function oldestRent() {\n    return $this-&gt;hasOne(Rent::class)-&gt;oldestOfMany();\n}<\/code><\/pre>\n<p>Por defecto, obtenemos los datos bas\u00e1ndonos en la clave primaria, que es ordenable, pero podemos crear nuestros propios filtros para el m\u00e9todo <strong>ofMany<\/strong>:<\/p>\n<pre><code class=\"language-php\">return $this-&gt;hasOne(Rent::class)-&gt;ofMany('price', 'min');<\/code><\/pre>\n<h2>Relaciones HasOneThrough y HasManyThrough<\/h2>\n<p>Los m\u00e9todos <strong>-Through <\/strong>sugieren que nuestros modelos tendr\u00e1n que pasar por otro modelo para establecer una relaci\u00f3n con el modelo deseado. Por ejemplo, podemos asociar el Alquiler con el Arrendador, pero el Alquiler debe pasar primero por el Arrendatario para llegar al Arrendador.<\/p>\n<p>Las claves de las tablas necesarias para ello tendr\u00edan el siguiente aspecto:<\/p>\n<pre><code class=\"language-bash\">rent\n    id - integer\n    name - string\n    value - double\n\ntenants\n    id - integer\n    name - string\n    rent_id - integer\n\nlandlord\n    id - integer\n    name - string\n    tenant_id - integer<\/code><\/pre>\n<p>Despu\u00e9s de visualizar el aspecto de nuestras tablas, podemos hacer los modelos:<\/p>\n<pre><code class=\"language-php\">&lt;?php\n\n<span id=\"urn:enhancement-fdc61b1f-bacd-4c55-9539-808af7ce758a\" class=\"textannotation\">namespace<\/span> <span id=\"urn:enhancement-aa5812ff-01f2-4cb8-a368-f358ea921b1d\" class=\"textannotation\">App<\/span>\\Models;\nuse Illuminate\\<span id=\"urn:enhancement-905245fa-78af-432c-9ed4-2e58c1680ff2\" class=\"textannotation\">Database<\/span>\\Eloquent\\<span id=\"urn:enhancement-f869f354-3e93-4616-83fc-09e2ae7ab039\" class=\"textannotation\">Model<\/span>;\n\nclass Rent extends Model\n{\n    \/**\n    * Return the rents' landlord\n    *\/\n    public function rentLandlord() \n    {\n        return $this-&gt;hasOneThrough(Landlord::class, Tenant::class);\n    }\n}<\/code><\/pre>\n<p>El primer argumento del m\u00e9todo <strong>hasOneThrough<\/strong> es el modelo al que quieres acceder, y el segundo argumento es el modelo por el que pasar\u00e1s.<\/p>\n<p>Y al igual que antes, puedes sobrescribir las claves for\u00e1neas y locales. Ahora que tenemos dos modelos, tenemos dos de cada para sobrescribir en este orden:<\/p>\n<pre><code class=\"language-php\">public function rentLandlord() \n{\n    return $this-&gt;hasOneThrough(\n        Landlord::class,\n        Tenant::class,\n        \"rent_id\",    \/\/ Foreign key on the tenant table\n        \"tenant_id\",  \/\/ Foreign key on the landlord table\n        \"id\",         \/\/ Local key on the tenant class\n        \"id\"          \/\/ Local key on the tenant table\n    );\n}<\/code><\/pre>\n<p>Del mismo modo, la relaci\u00f3n \u00abHas Many Through\u00bb de Laravel Eloquent es \u00fatil cuando quieres acceder a registros de una tabla lejana a trav\u00e9s de una tabla intermedia. Consideremos un ejemplo con tres tablas:<\/p>\n<ul>\n<li>pa\u00eds<\/li>\n<li>usuarios<\/li>\n<li>juegos<\/li>\n<\/ul>\n<p>Cada Pa\u00eds tiene muchos Usuarios, y cada Usuario tiene muchos Juegos. Queremos recuperar todos los Juegos pertenecientes a un Pa\u00eds a trav\u00e9s de la tabla Usuario.<\/p>\n<p>Definir\u00edas las tablas as\u00ed<\/p>\n<pre><code class=\"language-bash\">country\n    id - integer\n    name - string\n\nuser\n    id - integer\n    country_id - integer\n    name - string\n\ngames\n    id - integer\n    user_id - integer\n    title - string<\/code><\/pre>\n<p>Ahora debes definir el modelo Eloquent para cada una de las tablas:<\/p>\n<pre><code class=\"language-php\">&lt;?php\n\n<span id=\"urn:enhancement-b9e94720-2f95-4680-bb03-540b803e215d\" class=\"textannotation\">namespace<\/span> <span id=\"urn:enhancement-8f6a8b6c-1720-4fdd-b4e5-59aa4144e7ab\" class=\"textannotation\">App<\/span>\\Models;\nuse Illuminate\\<span id=\"urn:enhancement-5565b241-d69f-4bfd-9c27-0438775b5a71\" class=\"textannotation\">Database<\/span>\\Eloquent\\<span id=\"urn:enhancement-134a24ef-5d37-4d1a-87af-d297ebbb1bc4\" class=\"textannotation\">Model<\/span>;\n\nclass Country extends Model\n{\n    protected $fillable = ['name'];\n\n    public function users()\n    {\n        return $this-&gt;hasMany(User::class);\n    }\n\n    public function games()\n    {\n        return $this-&gt;hasManyThrough(Games::class, User::class);\n    }\n}<\/code><\/pre>\n<pre><code class=\"language-php\">&lt;?php\n\n<span id=\"urn:enhancement-d356ff4a-efd9-49b4-b879-d18efbff8a4e\" class=\"textannotation\">namespace<\/span> <span id=\"urn:enhancement-4b260579-b8ce-4f0b-9108-347f15ba32e1\" class=\"textannotation\">App<\/span>\\Models;\nuse Illuminate\\<span id=\"urn:enhancement-fde6251d-e2b5-4fca-9bbe-05eb0c3c114c\" class=\"textannotation\">Database<\/span>\\Eloquent\\<span id=\"urn:enhancement-3973274d-4af7-400c-b30b-b3be733d3054\" class=\"textannotation\">Model<\/span>;\n\nclass User extends Model\n{\n    protected $fillable = [article_id, 'name'];\n\n    public function country()\n    {\n        return $this-&gt;belongsTo(Country::class);\n    }\n\n    public function posts()\n    {\n        return $this-&gt;hasMany(Post::class);\n    }\n}<\/code><\/pre>\n<pre><code class=\"language-php\">&lt;?php\n\n<span id=\"urn:enhancement-174516fe-348f-46ff-b0ef-218b5e442243\" class=\"textannotation\">namespace<\/span> <span id=\"urn:enhancement-c9f579a3-37de-4987-8924-2b8226e8a5fc\" class=\"textannotation\">App<\/span>\\Models;\nuse Illuminate\\<span id=\"urn:enhancement-f62005e4-5328-4c48-b211-df5848a26a9a\" class=\"textannotation\">Database<\/span>\\Eloquent\\<span id=\"urn:enhancement-af88eb72-f9d0-4762-af2e-f7b83131f918\" class=\"textannotation\">Model<\/span>;\n\nclass Game extends Model\n{\n    protected $fillable = ['user_id', 'title'];\n\n    public function user()\n    {\n        return $this-&gt;belongsTo(User::class);\n    }\n}<\/code><\/pre>\n<p>Ahora podemos llamar al m\u00e9todo <strong>games() <\/strong>del modelo Pa\u00eds para obtener todos los juegos porque hemos establecido la relaci\u00f3n \u00abHas Many Through\u00bb entre Pa\u00eds y Juego a trav\u00e9s del modelo Usuario.<\/p>\n<pre><code class=\"language-php\">&lt;?php\n\n$country = Country::find(159);\n            \n\/\/ Retrieve all games for the country\n$games = $country-&gt;games;<\/code><\/pre>\n<h2>Relaci\u00f3n Varios-a-Varios<\/h2>\n<p>La relaci\u00f3n varios-a-varios es m\u00e1s complicada. Un buen ejemplo es un empleado que tiene varios roles. Un rol tambi\u00e9n puede asignarse a varios empleados. \u00c9sta es la base de la relaci\u00f3n de muchos a muchos.<\/p>\n<p>Para ello, debemos tener las tablas <strong>employees<\/strong>,\u00a0<strong>roles<\/strong> y\u00a0<strong>role_employees<\/strong>.<\/p>\n<p>La estructura de las tablas de nuestra base de datos ser\u00e1 la siguiente<\/p>\n<pre><code class=\"language-bash\">employees\n    id - integer\n    name - string\n\nroles \n    id - integer\n    name - string\n\nrole_employees\n    user_id - integer\n    role_id - integer<\/code><\/pre>\n<p>Conociendo la estructura de tablas de la relaci\u00f3n, podemos definir f\u00e1cilmente nuestro<strong> modelo de Employee<\/strong> para <strong>belongsToMany Role<\/strong> model.<\/p>\n<pre><code class=\"language-php\">&lt;?php\n\n<span id=\"urn:enhancement-518a35a3-415b-4403-842b-325e2fe91aa4\" class=\"textannotation\">namespace<\/span> <span id=\"urn:enhancement-85aa42f0-0834-46ec-8eba-d343015bedd2\" class=\"textannotation\">App<\/span>\\Models;\nuse Illuminate\\<span id=\"urn:enhancement-7f2a9519-58b1-49db-a095-8752da2a21bd\" class=\"textannotation\">Database<\/span>\\Eloquent\\<span id=\"urn:enhancement-3b68780a-691e-4452-a518-2212db0ef62b\" class=\"textannotation\">Model<\/span>;\n\nclass Employee extends Model\n{\n    public function roles() \n    {\n        return $this- &gt;belongsToMany(Role::class);\n    }\n}<\/code><\/pre>\n<p>Una vez definido esto, podemos acceder a todos los roles de un empleado e incluso filtrarlos:<\/p>\n<pre><code class=\"language-php\">$employee = Employee::find(1);\n$employee-&gt;roles-&gt;forEach(function($role) { \/\/ });\n\n\/\/ OR \n\n$employee = Employee::find(1)-&gt;roles()-&gt;orderBy('name')-&gt;where('name', 'admin')-&gt;get();<\/code><\/pre>\n<p>Como todos los dem\u00e1s m\u00e9todos, podemos sobrescribir las claves for\u00e1neas y locales del m\u00e9todo <strong>belongsToMany<\/strong>.<\/p>\n<p>Para definir la relaci\u00f3n inversa del <strong>belongsToMany<\/strong> simplemente utilizamos el mismo m\u00e9todo pero sobre el m\u00e9todo hijo ahora, con el padre como argumento.<\/p>\n<pre><code class=\"language-php\">&lt;?php\n\n<span id=\"urn:enhancement-e1589f86-81ad-4098-9d8c-0ccf1d7d49c7\" class=\"textannotation\">namespace<\/span> <span id=\"urn:enhancement-a7137c01-362a-4c28-93de-6c8de8b234ca\" class=\"textannotation\">App<\/span>\\Models;\nuse Illuminate\\<span id=\"urn:enhancement-29c5bb6e-553e-4196-8350-c18db125b742\" class=\"textannotation\">Database<\/span>\\Eloquent\\<span id=\"urn:enhancement-ca5c6a4a-e0e1-43b6-903c-53f4cd35f911\" class=\"textannotation\">Model<\/span>;\n\nclass Role extends Model\n{\n    public function employees() \n    {\n        return $this-&gt;belongsToMany(Employee::class);\n    }\n}<\/code><\/pre>\n<h3>Usos de la tabla intermedia<\/h3>\n<p>Como habr\u00e1s notado, cuando utilizamos la relaci\u00f3n varios-a-varios, siempre se supone que tenemos una tabla intermedia. En este caso, estamos utilizando la tabla <strong>role_employees<\/strong>.<\/p>\n<p>Por defecto, nuestra tabla pivotante contendr\u00e1 s\u00f3lo los atributos id. Si queremos otros atributos, tenemos que especificarlos as\u00ed:<\/p>\n<pre><code class=\"language-php\">return $this-&gt;belongsToMany(Employee::class)-&gt;withPivot(\"active\", \"created_at\");<\/code><\/pre>\n<p>Si queremos abreviar el pivote para las marcas de tiempo, podemos hacerlo:<\/p>\n<pre><code class=\"language-php\">return $this-&gt;belongsToMany(Employee::class)-&gt;withTimestamps();<\/code><\/pre>\n<p>Un truco que hay que saber es que podemos personalizar el nombre \u00abpivote\u00bb en cualquier cosa que se adapte mejor a nuestra aplicaci\u00f3n:<\/p>\n<pre><code class=\"language-php\">return $this-&gt;belongsToMany(Employee::class)-&gt;as('subscription')-&gt;withPivot(\"active\", \"created_by\");<\/code><\/pre>\n<p>Filtrar los resultados de una consulta elocuente es un conocimiento imprescindible para cualquier desarrollador que quiera dar un paso adelante y <a href=\"https:\/\/kinsta.com\/es\/blog\/rendimiento-laravel\/\">optimizar sus aplicaciones Laravel<\/a>.<\/p>\n<p>Por lo tanto, Laravel proporciona una fant\u00e1stica caracter\u00edstica de pivotes que se puede utilizar para filtrar los datos que queremos recopilar. As\u00ed, en lugar de utilizar otras funciones como <a href=\"https:\/\/kinsta.com\/es\/blog\/base-de-datos-de-laravel\/\">las transacciones de base de datos<\/a> para obtener nuestros datos a trozos, podemos filtrarlos con m\u00e9todos \u00fatiles como <strong>wherePivot, wherePivotIn, wherePivotNotIn, wherePivotBetween, wherePivotNotBetween, wherePivotNull, wherePivotNotNull<\/strong> \u00a1y podemos utilizarlos al definir relaciones entre tablas!<\/p>\n<pre><code class=\"language-php\">return $this-&gt;belongsToMany(Employee::class)-&gt;wherePivot('promoted', 1);\nreturn $this-&gt;belongsToMany(Employee::class)-&gt;wherePivotIn('level', [1, 2]);\nreturn $this-&gt;belongsToMany(Employee::class)-&gt;wherePivotNotIn('level', [2, 3]);\nreturn $this-&gt;belongsToMany(Employee::class)-&gt;wherePivotBetween('posted_at', ['2023-01-01 00:00:00', '2023-01-02 00:00:00']);\nreturn $this-&gt;belongsToMany(Employee::class)-&gt;wherePivotNull('expired_at');\nreturn $this-&gt;belongsToMany(Employee::class)-&gt;wherePivotNotNull('posted_at');<\/code><\/pre>\n<p>Una \u00faltima caracter\u00edstica sorprendente es que podemos ordenar por pivotes:<\/p>\n<pre><code class=\"language-php\">return $this-&gt;belongsToMany(Employee::class)\n        -&gt;where('promoted', true)\n        -&gt;orderByPivot('hired_at', 'desc');<\/code><\/pre>\n<h2>Relaciones Polim\u00f3rficas<\/h2>\n<p>La palabra Polim\u00f3rfico viene del griego, y significa \u00abmuchas formas\u00bb As\u00ed, un modelo de nuestra aplicaci\u00f3n puede adoptar muchas formas, es decir, puede tener m\u00e1s de una asociaci\u00f3n. Imagina que estamos construyendo una aplicaci\u00f3n con blogs, v\u00eddeos, encuestas, etc. Un usuario puede crear un comentario para cualquiera de ellos. Por tanto, un <strong>modelo Comentario<\/strong> podr\u00eda pertenecer a los modelos <strong>Blogs<\/strong>, <strong>V\u00eddeos<\/strong> y <strong>Encuestas<\/strong>.<\/p>\n<h2>Polim\u00f3rfico Uno a Uno<\/h2>\n<p>Este tipo de relaci\u00f3n es similar a una relaci\u00f3n est\u00e1ndar uno a uno. La \u00fanica diferencia es que el modelo hijo puede pertenecer a m\u00e1s de un tipo de modelo con una \u00fanica asociaci\u00f3n.<\/p>\n<p>Tomemos, por ejemplo, un modelo de <strong>Tenant<\/strong><strong>\u00a0<\/strong>y <strong>Landlord<\/strong>, puede compartir una relaci\u00f3n polim\u00f3rfica con un modelo de <strong>WaterBill<\/strong>.<\/p>\n<p>La estructura de la tabla puede ser la siguiente:<\/p>\n<pre><code class=\"language-bash\">tenants\n    id \u2013 integer\n    name \u2013 string\n\nlandlords\n    id \u2013 integer\n    name \u2013 string\n\nwaterbills\n    id \u2013 integer\n    amount \u2013 double\n    waterbillable_id\n    waterbillable_type<\/code><\/pre>\n<p>Utilizamos waterbillable_id para el id del <strong>landlord\u00a0<\/strong>o <strong>tenant<\/strong>, mientras que waterbillable_type contiene el nombre de la clase del modelo padre. La columna tipo la utiliza eloquent para averiguar qu\u00e9 modelo padre debe devolver.<\/p>\n<p>La definici\u00f3n del modelo para una relaci\u00f3n de este tipo tendr\u00e1 el siguiente aspecto:<\/p>\n<pre><code class=\"language-php\">&lt;?php\n\n<span id=\"urn:enhancement-7bd6f49f-68df-4888-8bc5-fc09c79ced0e\" class=\"textannotation\">namespace<\/span> <span id=\"urn:enhancement-523ef47b-c6d5-493d-8970-61a1c3c17726\" class=\"textannotation\">App<\/span>\\Models;\nuse Illuminate\\<span id=\"urn:enhancement-c7a54312-4ddf-4187-bac6-ae55404bbafb\" class=\"textannotation\">Database<\/span>\\Eloquent\\<span id=\"urn:enhancement-181614ed-1c17-4247-a828-7c4f68779be6\" class=\"textannotation\">Model<\/span>;\n\nclass WaterBill extends Model\n{\n    public function billable()\n    {\n        return $this-&gt;morphTo();\n    }\n}\n\nclass Tenant extends Model\n{\n    public function waterBill()    \n    {\n        return $this-&gt;morphOne(WaterBill::class, 'billable');\n    }\n}\n\nclass Landlord extends Model\n{\n    public function waterBill()    \n    {\n        return $this-&gt;morphOne(WaterBill::class, 'billable');\n    }\n}<\/code><\/pre>\n<p>Una vez que tengamos todo esto en su sitio, podremos acceder a los datos tanto del modelo Propietario como del modelo Inquilino:<\/p>\n<pre><code class=\"language-php\">&lt;?php\n\n$tenant = Tenant::find(1)-&gt;waterBill;\n$landlord = Landlord::find(1)-&gt;waterBill;<\/code><\/pre>\n<h2>Polim\u00f3rfico Uno a Varios<\/h2>\n<p>Es similar a una relaci\u00f3n normal de uno a varios, la \u00fanica diferencia clave es que el modelo hijo puede pertenecer a m\u00e1s de un tipo de modelo, utilizando una \u00fanica asociaci\u00f3n.<\/p>\n<p>En una aplicaci\u00f3n como Facebook, los usuarios pueden comentar publicaciones, v\u00eddeos, encuestas, directos, etc. Con un uno a muchos polim\u00f3rfico, podemos utilizar una \u00fanica tabla de <strong>comentarios<\/strong> para almacenar los comentarios de todas las categor\u00edas que tengamos. La estructura de nuestra tabla ser\u00eda algo as\u00ed<\/p>\n<pre><code class=\"language-bash\">posts \n    id \u2013 integer\n    title \u2013 string\n    body \u2013 text\n\nvideos\n    id \u2013 integer\n    title \u2013 string\n    url \u2013 string\n\npolls\n    id \u2013 integer\n    title \u2013 string\n\ncomments \n    id \u2013 integer\n    body \u2013 text\n    commentable_id \u2013 integer\n    commentable_type \u2013 string<\/code><\/pre>\n<p>El commentable_id siendo el id del registro, y el commentable_type siendo el tipo de clase, para que eloquent sepa qu\u00e9 buscar. En cuanto a la estructura del modelo, es muy similar al polim\u00f3rfico uno a muchos:<\/p>\n<pre><code class=\"language-php\">&lt;?php\n\n<span id=\"urn:enhancement-7bd6f49f-68df-4888-8bc5-fc09c79ced0e\" class=\"textannotation\">namespace<\/span> <span id=\"urn:enhancement-523ef47b-c6d5-493d-8970-61a1c3c17726\" class=\"textannotation\">App<\/span>\\Models;\nuse Illuminate\\<span id=\"urn:enhancement-c7a54312-4ddf-4187-bac6-ae55404bbafb\" class=\"textannotation\">Database<\/span>\\Eloquent\\<span id=\"urn:enhancement-181614ed-1c17-4247-a828-7c4f68779be6\" class=\"textannotation\">Model<\/span>;\n\nclass Comment extends Model \n{\n    public function commentable()\n    {\n        return $this-&gt;morphTo();\n    }\n}\n\nclass Poll extends Model\n{\n    public function comments()\n    {\n        return $this-&gt;morphMany(Comment::class, 'commentable');\n    }\n}\n\nclass Live extends Model\n{\n    public function comments()\n    {\n        return $this-&gt;morphMany(Comments::class, 'commentable');\n    }\n}<\/code><\/pre>\n<p>Ahora, para recuperar los comentarios de un Vivo, basta con llamar al m\u00e9todo encontrar con el id, y ya tenemos acceso a la clase iterable comentarios:<\/p>\n<pre><code class=\"language-php\">&lt;?php\n\nuse <span id=\"urn:enhancement-460d5b0f-968a-4437-a4b9-f9a7f29fdc3a\" class=\"textannotation\">App<\/span>\\Models\\Live;\n\n$live = Live::find(1);\n\nforeach ($live-&gt;comments as $comment) { }\n\n\/\/ OR\n\nLive::find(1)-&gt;comments()-&gt;each(function($comment) { \/\/ });\nLive::find(1)-&gt;comments()-&gt;map(function($comment) { \/\/ });\nLive::find(1)-&gt;comments()-&gt;filter(function($comment) { \/\/ });\n\n\/\/ etc.<\/code><\/pre>\n<p>Y si tenemos el comentario y queremos averiguar a qui\u00e9n pertenece, accedemos al m\u00e9todo commentable:<\/p>\n<pre><code class=\"language-php\">&lt;?php\n\nuse <span id=\"urn:enhancement-a28e1536-2335-4a7e-82f0-52049cd1632e\" class=\"textannotation\">App<\/span>\\Models\\<span id=\"urn:enhancement-0941b42e-928b-4546-957d-b206cc8f86db\" class=\"textannotation\">Comment<\/span>;\n\n$comment = Comment::find(10);\n$commentable = $comment-&gt;commentable;\n\n\/\/ commentable \u2013 type of Post, Video, Poll, Live<\/code><\/pre>\n<h2>Polim\u00f3rfico Uno a Varios<\/h2>\n<p>En muchas aplicaciones que escalan, queremos una forma f\u00e1cil de interactuar con los modelos y entre ellos. Podemos querer el primer o el \u00faltimo comentario de un usuario, lo que puede hacerse con una combinaci\u00f3n de m\u00e9todos <strong>morphOne<\/strong> y <strong>ofMany<\/strong>:<\/p>\n<pre><code class=\"language-php\">&lt;?php\n\npublic function latestPost()\n{\n    return $this-&gt;morphOne(Post::class, 'postable')-&gt;latestOfMany();\n}\n\npublic function oldestPost()\n{\n    return $this-&gt;morphOne(Post::class, 'postable')-&gt;oldestOfMany();\n}<\/code><\/pre>\n<p>Los m\u00e9todos <strong>latestOfMany<\/strong> y <strong>oldestOfMany <\/strong>recuperan el modelo m\u00e1s reciente o m\u00e1s antiguo bas\u00e1ndose en la clave primaria del modelo, que era la condici\u00f3n de que fuera ordenable.<\/p>\n<p>En algunos casos, no queremos ordenar por el ID, tal vez cambiamos la fecha de publicaci\u00f3n de algunas entradas y las queremos en ese orden, no por su id.<\/p>\n<p>Para ello podemos pasar 2 par\u00e1metros al m\u00e9todo <strong>ofMany<\/strong>. El primer par\u00e1metro es la <strong>clave<\/strong> por la que queremos filtrar, y el segundo es el <strong>m\u00e9todo de ordenaci\u00f3n<\/strong>:<\/p>\n<pre><code class=\"language-php\">&lt;?php\n\npublic function latestPublishedPost()\n{\n    return $this-&gt;morphOne(Post::class, \"postable\")-&gt;ofMany(\"published_at\", \"max\");\n}<\/code><\/pre>\n<p>Teniendo esto en cuenta, \u00a1es posible construir relaciones m\u00e1s avanzadas para esto! Imagina que tenemos este escenario. Se nos pide que generemos una lista de todas las entradas actuales en el orden en que han sido publicadas. El problema surge cuando tenemos 2 entradas con el mismo valor de published_at y cuando las entradas est\u00e1n programadas para publicarse en el futuro.<\/p>\n<p>Para ello, podemos pasar al m\u00e9todo <strong>ofMany<\/strong> el orden en el que queremos que se apliquen los filtros. De esta forma ordenamos por published_at, y si son iguales, ordenamos por id. En segundo lugar, podemos aplicar una funci\u00f3n de consulta al m\u00e9todo <strong>ofMany<\/strong> para excluir todas las entradas cuya publicaci\u00f3n est\u00e9 programada<\/p>\n<pre><code class=\"language-php\">&lt;?php\n\npublic function currentPosts()\n{\n    return $this-&gt;hasOne(Post::class)-&gt;ofMany([\n        'published_at' =&gt; 'max',\n        'id' =&gt; 'max',\n    ], function ($query) {\n        $query-&gt;where('published_at', '&lt;', now());\n    });\n}<\/code><\/pre>\n<h2>Polim\u00f3rfico Varios a Varios<\/h2>\n<p>El varios-a-varios polim\u00f3rfico es ligeramente m\u00e1s complejo que el normal. Una situaci\u00f3n com\u00fan es tener etiquetas que se aplican a m\u00e1s activos en tu aplicaci\u00f3n. Por ejemplo, en TikTok, tenemos etiquetas que se pueden aplicar a V\u00eddeos, Cortos, Historias, etc.<\/p>\n<p>El polim\u00f3rfico varios-a-varios nos permite tener una \u00fanica tabla de etiquetas asociadas a los V\u00eddeos, Cortos e Historias.<\/p>\n<p>La estructura de la tabla es sencilla:<\/p>\n<pre><code class=\"language-bash\">videos\n    id \u2013 integer\n    description \u2013 string\n\nstories \n    id \u2013 integer\n    description \u2013 string\n\ntaggables \n    tag_id \u2013 integer\n    taggable_id \u2013 integer\n    taggable_type \u2013 string<\/code><\/pre>\n<p>Con las tablas listas, podemos hacer el modelo y utilizar el m\u00e9todo <strong>morphToMany<\/strong>. Este m\u00e9todo acepta el nombre de la clase del modelo y el \u00abnombre de la relaci\u00f3n\u00bb:<\/p>\n<pre><code class=\"language-php\">&lt;?php\n\n<span id=\"urn:enhancement-8139a88b-958d-4dee-a76c-d5efe885bdb0\" class=\"textannotation\">namespace<\/span> <span id=\"urn:enhancement-5b25171a-680a-475a-81e5-1b8ed9d43532\" class=\"textannotation\">App<\/span>\\Models;\nuse Illuminate\\<span id=\"urn:enhancement-fe8869dd-7abc-41fb-8b3c-868d76639ac0\" class=\"textannotation\">Database<\/span>\\Eloquent\\<span id=\"urn:enhancement-b57cf12b-3753-4bad-98e6-92a801d76ab0\" class=\"textannotation\">Model<\/span>;\n\nclass Video extends Model\n{\n    public function tags()\n    {\n        return $this-&gt;morphToMany(Tag::class, 'taggable');\n    }\n}<\/code><\/pre>\n<p>Y con esto, podemos definir f\u00e1cilmente la relaci\u00f3n inversa. Sabemos que para cada modelo hijo queremos llamar al m\u00e9todo <strong>morphedByMany<\/strong>:<\/p>\n<pre><code class=\"language-php\">&lt;?php\n\n<span id=\"urn:enhancement-8139a88b-958d-4dee-a76c-d5efe885bdb0\" class=\"textannotation\">namespace<\/span> <span id=\"urn:enhancement-5b25171a-680a-475a-81e5-1b8ed9d43532\" class=\"textannotation\">App<\/span>\\Models;\nuse Illuminate\\<span id=\"urn:enhancement-fe8869dd-7abc-41fb-8b3c-868d76639ac0\" class=\"textannotation\">Database<\/span>\\Eloquent\\<span id=\"urn:enhancement-b57cf12b-3753-4bad-98e6-92a801d76ab0\" class=\"textannotation\">Model<\/span>;\n\nclass Tag extends Model\n{\n    public function stories()\n    {\n        return $this-&gt;morphedByMany(Story::class, 'taggable');\n    }\n\n    public function videos()\n    {\n        return $this-&gt;morphedByMany(Video::class, 'taggable');\n    } \n}<\/code><\/pre>\n<p>Y ahora, cuando obtengamos una etiqueta, \u00a1podremos recuperar todos los v\u00eddeos e historias relacionados con esa etiqueta!<\/p>\n<pre><code class=\"language-php\">&lt;?php\nuse <span id=\"urn:enhancement-3ab28861-b1dc-411e-bc58-a349a014ff8a\" class=\"textannotation\">App<\/span>\\<span id=\"urn:enhancement-db43365c-bee4-4b95-92af-0e88e4d3f9bb\" class=\"textannotation\">Model<\/span>\\<span id=\"urn:enhancement-d8ae0a62-d7a9-4d7d-a2b4-81514400dbca\" class=\"textannotation\">Tag<\/span>;\n\n$tag = Tag::find(10);\n$posts = $tag-&gt;stories;\n$videos = $tag-&gt;stories;<\/code><\/pre>\n<h2>Optimiza la velocidad de Eloquent<\/h2>\n<p>Cuando trabajes con el ORM Eloquent de Laravel, es esencial que sepas c\u00f3mo optimizar las consultas a la base de datos y minimizar la cantidad de tiempo y memoria que requiere la obtenci\u00f3n de datos. Una forma de hacerlo es <a href=\"https:\/\/kinsta.com\/es\/blog\/laravel-caching\/\">implementando el almacenamiento en cach\u00e9<\/a> en tu aplicaci\u00f3n.<\/p>\n<p>Laravel proporciona un sistema de almacenamiento en cach\u00e9 flexible que admite varios backends, como <a href=\"https:\/\/redis.io\/\" target=\"_blank\" rel=\"noopener noreferrer\">Redis<\/a>, <a href=\"https:\/\/memcached.org\/\" target=\"_blank\" rel=\"noopener noreferrer\">Memcached<\/a> y <a href=\"https:\/\/www.ibm.com\/docs\/en\/zvm\/7.1?topic=reference-file-caching\" target=\"_blank\" rel=\"noopener noreferrer\">almacenamiento en cach\u00e9 basado en archivos<\/a>. Al almacenar en cach\u00e9 los resultados de las consultas de Eloquent, puedes reducir el n\u00famero de consultas a la base de datos, haciendo que tu aplicaci\u00f3n sea m\u00e1s r\u00e1pida y valiosa.<\/p>\n<p>Adem\u00e1s, puedes utilizar el <a href=\"https:\/\/laravel.com\/docs\/10.x\/queries\" target=\"_blank\" rel=\"noopener noreferrer\">constructor de consultas<\/a> de Laravel para crear consultas complejas adicionales, optimizando a\u00fan m\u00e1s el rendimiento de tu aplicaci\u00f3n.<\/p>\n<h2>Resumen<\/h2>\n<p>En conclusi\u00f3n, las relaciones Eloquent son una potente caracter\u00edstica de Laravel que permite a los desarrolladores trabajar f\u00e1cilmente con datos relacionados. Desde relaciones uno a uno hasta relaciones varios a varios, Eloquent proporciona una sintaxis sencilla e intuitiva para definir y consultar estas relaciones.<\/p>\n<p>Como desarrollador de Laravel, dominar las relaciones Eloquent puede mejorar enormemente tu flujo de trabajo de desarrollo y hacer que tu c\u00f3digo sea m\u00e1s eficiente y legible. Si est\u00e1s interesado en aprender m\u00e1s sobre Laravel, Kinsta tiene varios recursos disponibles, incluido un <a href=\"https:\/\/kinsta.com\/es\/blog\/tutoriales-laravel\/\">tutorial<\/a> sobre c\u00f3mo empezar con Laravel y un art\u00edculo sobre <a href=\"https:\/\/kinsta.com\/es\/blog\/salario-desarrolladores-laravel\/\">los salarios de los desarrolladores de Laravel.<\/a><\/p>\n<p>Kinsta ofrece soluciones de alojamiento gestionado que facilitan el <a href=\"https:\/\/sevalla.com\/application-hosting\/\">despliegue y la gesti\u00f3n de aplicaciones<\/a> Laravel.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A menudo llega un momento en la vida de todo desarrollador en el que tienes que interactuar con una base de datos. Aqu\u00ed es donde Eloquent, &#8230;<\/p>\n","protected":false},"author":267,"featured_media":66684,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_kinsta_gated_content":false,"_kinsta_gated_content_redirect":"","footnotes":""},"tags":[],"topic":[1337,1303],"class_list":["post-66683","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","topic-herramientas-de-desarrollo-web","topic-laravel"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v24.6 (Yoast SEO v24.6) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Relaciones de Laravel Eloquent: Gu\u00eda Avanzada - Kinsta\u00ae<\/title>\n<meta name=\"description\" content=\"Cuando trabajamos con tablas en una base de datos relacional, podemos caracterizar las distintas y complejas relaciones como conexiones entre tablas.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/kinsta.com\/es\/blog\/laravel-relaciones\/\" \/>\n<meta property=\"og:locale\" content=\"es_ES\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Las Relaciones de Laravel Eloquent: Una Gu\u00eda Avanzada\" \/>\n<meta property=\"og:description\" content=\"Cuando trabajamos con tablas en una base de datos relacional, podemos caracterizar las distintas y complejas relaciones como conexiones entre tablas.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/kinsta.com\/es\/blog\/laravel-relaciones\/\" \/>\n<meta property=\"og:site_name\" content=\"Kinsta\u00ae\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/kinsta.es\/\" \/>\n<meta property=\"article:published_time\" content=\"2023-06-07T17:18:09+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-01-17T12:50:54+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2023\/06\/laravel-relationships.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1460\" \/>\n\t<meta property=\"og:image:height\" content=\"730\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Coman Cosmin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:description\" content=\"Cuando trabajamos con tablas en una base de datos relacional, podemos caracterizar las distintas y complejas relaciones como conexiones entre tablas.\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2023\/06\/laravel-relationships.jpg\" \/>\n<meta name=\"twitter:creator\" content=\"@Kinsta_ES\" \/>\n<meta name=\"twitter:site\" content=\"@Kinsta_ES\" \/>\n<meta name=\"twitter:label1\" content=\"Escrito por\" \/>\n\t<meta name=\"twitter:data1\" content=\"Coman Cosmin\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tiempo de lectura\" \/>\n\t<meta name=\"twitter:data2\" content=\"14 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/kinsta.com\/es\/blog\/laravel-relaciones\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/kinsta.com\/es\/blog\/laravel-relaciones\/\"},\"author\":{\"name\":\"Coman Cosmin\",\"@id\":\"https:\/\/kinsta.com\/es\/#\/schema\/person\/aa307e51da3929c7aead1f4b4439f3da\"},\"headline\":\"Las Relaciones de Laravel Eloquent: Una Gu\u00eda Avanzada\",\"datePublished\":\"2023-06-07T17:18:09+00:00\",\"dateModified\":\"2025-01-17T12:50:54+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/kinsta.com\/es\/blog\/laravel-relaciones\/\"},\"wordCount\":2499,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/kinsta.com\/es\/#organization\"},\"image\":{\"@id\":\"https:\/\/kinsta.com\/es\/blog\/laravel-relaciones\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2023\/06\/laravel-relationships.jpg\",\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/kinsta.com\/es\/blog\/laravel-relaciones\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/kinsta.com\/es\/blog\/laravel-relaciones\/\",\"url\":\"https:\/\/kinsta.com\/es\/blog\/laravel-relaciones\/\",\"name\":\"Relaciones de Laravel Eloquent: Gu\u00eda Avanzada - Kinsta\u00ae\",\"isPartOf\":{\"@id\":\"https:\/\/kinsta.com\/es\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/kinsta.com\/es\/blog\/laravel-relaciones\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/kinsta.com\/es\/blog\/laravel-relaciones\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2023\/06\/laravel-relationships.jpg\",\"datePublished\":\"2023-06-07T17:18:09+00:00\",\"dateModified\":\"2025-01-17T12:50:54+00:00\",\"description\":\"Cuando trabajamos con tablas en una base de datos relacional, podemos caracterizar las distintas y complejas relaciones como conexiones entre tablas.\",\"breadcrumb\":{\"@id\":\"https:\/\/kinsta.com\/es\/blog\/laravel-relaciones\/#breadcrumb\"},\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/kinsta.com\/es\/blog\/laravel-relaciones\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/kinsta.com\/es\/blog\/laravel-relaciones\/#primaryimage\",\"url\":\"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2023\/06\/laravel-relationships.jpg\",\"contentUrl\":\"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2023\/06\/laravel-relationships.jpg\",\"width\":1460,\"height\":730},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/kinsta.com\/es\/blog\/laravel-relaciones\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/kinsta.com\/es\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Laravel\",\"item\":\"https:\/\/kinsta.com\/es\/secciones\/laravel\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Las Relaciones de Laravel Eloquent: Una Gu\u00eda Avanzada\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/kinsta.com\/es\/#website\",\"url\":\"https:\/\/kinsta.com\/es\/\",\"name\":\"Kinsta\u00ae\",\"description\":\"Soluciones de alojamiento premium, r\u00e1pidas y seguras\",\"publisher\":{\"@id\":\"https:\/\/kinsta.com\/es\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/kinsta.com\/es\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"es\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/kinsta.com\/es\/#organization\",\"name\":\"Kinsta\",\"url\":\"https:\/\/kinsta.com\/es\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/kinsta.com\/es\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2023\/12\/kinsta-logo.jpeg\",\"contentUrl\":\"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2023\/12\/kinsta-logo.jpeg\",\"width\":500,\"height\":500,\"caption\":\"Kinsta\"},\"image\":{\"@id\":\"https:\/\/kinsta.com\/es\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/kinsta.es\/\",\"https:\/\/x.com\/Kinsta_ES\",\"https:\/\/www.instagram.com\/kinstahosting\/\",\"https:\/\/www.linkedin.com\/company\/kinsta\/\",\"https:\/\/www.pinterest.com\/kinstahosting\/\",\"https:\/\/www.youtube.com\/c\/Kinsta\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/kinsta.com\/es\/#\/schema\/person\/aa307e51da3929c7aead1f4b4439f3da\",\"name\":\"Coman Cosmin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/kinsta.com\/es\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/ede71ae86b38c64bcf00417fd17a686b?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/ede71ae86b38c64bcf00417fd17a686b?s=96&d=mm&r=g\",\"caption\":\"Coman Cosmin\"},\"description\":\"Cosmin Coman is a technology writer and developer with over 3 years of experience. Apart from writing for Kinsta, he has assisted in research at nuclear physics facilities and universities. Tech-savvy and integrated into the community, he always comes up with innovative solutions.\",\"url\":\"https:\/\/kinsta.com\/es\/blog\/author\/comancosmin\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Relaciones de Laravel Eloquent: Gu\u00eda Avanzada - Kinsta\u00ae","description":"Cuando trabajamos con tablas en una base de datos relacional, podemos caracterizar las distintas y complejas relaciones como conexiones entre tablas.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/kinsta.com\/es\/blog\/laravel-relaciones\/","og_locale":"es_ES","og_type":"article","og_title":"Las Relaciones de Laravel Eloquent: Una Gu\u00eda Avanzada","og_description":"Cuando trabajamos con tablas en una base de datos relacional, podemos caracterizar las distintas y complejas relaciones como conexiones entre tablas.","og_url":"https:\/\/kinsta.com\/es\/blog\/laravel-relaciones\/","og_site_name":"Kinsta\u00ae","article_publisher":"https:\/\/www.facebook.com\/kinsta.es\/","article_published_time":"2023-06-07T17:18:09+00:00","article_modified_time":"2025-01-17T12:50:54+00:00","og_image":[{"width":1460,"height":730,"url":"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2023\/06\/laravel-relationships.jpg","type":"image\/jpeg"}],"author":"Coman Cosmin","twitter_card":"summary_large_image","twitter_description":"Cuando trabajamos con tablas en una base de datos relacional, podemos caracterizar las distintas y complejas relaciones como conexiones entre tablas.","twitter_image":"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2023\/06\/laravel-relationships.jpg","twitter_creator":"@Kinsta_ES","twitter_site":"@Kinsta_ES","twitter_misc":{"Escrito por":"Coman Cosmin","Tiempo de lectura":"14 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/kinsta.com\/es\/blog\/laravel-relaciones\/#article","isPartOf":{"@id":"https:\/\/kinsta.com\/es\/blog\/laravel-relaciones\/"},"author":{"name":"Coman Cosmin","@id":"https:\/\/kinsta.com\/es\/#\/schema\/person\/aa307e51da3929c7aead1f4b4439f3da"},"headline":"Las Relaciones de Laravel Eloquent: Una Gu\u00eda Avanzada","datePublished":"2023-06-07T17:18:09+00:00","dateModified":"2025-01-17T12:50:54+00:00","mainEntityOfPage":{"@id":"https:\/\/kinsta.com\/es\/blog\/laravel-relaciones\/"},"wordCount":2499,"commentCount":0,"publisher":{"@id":"https:\/\/kinsta.com\/es\/#organization"},"image":{"@id":"https:\/\/kinsta.com\/es\/blog\/laravel-relaciones\/#primaryimage"},"thumbnailUrl":"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2023\/06\/laravel-relationships.jpg","inLanguage":"es","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/kinsta.com\/es\/blog\/laravel-relaciones\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/kinsta.com\/es\/blog\/laravel-relaciones\/","url":"https:\/\/kinsta.com\/es\/blog\/laravel-relaciones\/","name":"Relaciones de Laravel Eloquent: Gu\u00eda Avanzada - Kinsta\u00ae","isPartOf":{"@id":"https:\/\/kinsta.com\/es\/#website"},"primaryImageOfPage":{"@id":"https:\/\/kinsta.com\/es\/blog\/laravel-relaciones\/#primaryimage"},"image":{"@id":"https:\/\/kinsta.com\/es\/blog\/laravel-relaciones\/#primaryimage"},"thumbnailUrl":"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2023\/06\/laravel-relationships.jpg","datePublished":"2023-06-07T17:18:09+00:00","dateModified":"2025-01-17T12:50:54+00:00","description":"Cuando trabajamos con tablas en una base de datos relacional, podemos caracterizar las distintas y complejas relaciones como conexiones entre tablas.","breadcrumb":{"@id":"https:\/\/kinsta.com\/es\/blog\/laravel-relaciones\/#breadcrumb"},"inLanguage":"es","potentialAction":[{"@type":"ReadAction","target":["https:\/\/kinsta.com\/es\/blog\/laravel-relaciones\/"]}]},{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/kinsta.com\/es\/blog\/laravel-relaciones\/#primaryimage","url":"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2023\/06\/laravel-relationships.jpg","contentUrl":"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2023\/06\/laravel-relationships.jpg","width":1460,"height":730},{"@type":"BreadcrumbList","@id":"https:\/\/kinsta.com\/es\/blog\/laravel-relaciones\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/kinsta.com\/es\/"},{"@type":"ListItem","position":2,"name":"Laravel","item":"https:\/\/kinsta.com\/es\/secciones\/laravel\/"},{"@type":"ListItem","position":3,"name":"Las Relaciones de Laravel Eloquent: Una Gu\u00eda Avanzada"}]},{"@type":"WebSite","@id":"https:\/\/kinsta.com\/es\/#website","url":"https:\/\/kinsta.com\/es\/","name":"Kinsta\u00ae","description":"Soluciones de alojamiento premium, r\u00e1pidas y seguras","publisher":{"@id":"https:\/\/kinsta.com\/es\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/kinsta.com\/es\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"es"},{"@type":"Organization","@id":"https:\/\/kinsta.com\/es\/#organization","name":"Kinsta","url":"https:\/\/kinsta.com\/es\/","logo":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/kinsta.com\/es\/#\/schema\/logo\/image\/","url":"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2023\/12\/kinsta-logo.jpeg","contentUrl":"https:\/\/kinsta.com\/es\/wp-content\/uploads\/sites\/8\/2023\/12\/kinsta-logo.jpeg","width":500,"height":500,"caption":"Kinsta"},"image":{"@id":"https:\/\/kinsta.com\/es\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/kinsta.es\/","https:\/\/x.com\/Kinsta_ES","https:\/\/www.instagram.com\/kinstahosting\/","https:\/\/www.linkedin.com\/company\/kinsta\/","https:\/\/www.pinterest.com\/kinstahosting\/","https:\/\/www.youtube.com\/c\/Kinsta"]},{"@type":"Person","@id":"https:\/\/kinsta.com\/es\/#\/schema\/person\/aa307e51da3929c7aead1f4b4439f3da","name":"Coman Cosmin","image":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/kinsta.com\/es\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/ede71ae86b38c64bcf00417fd17a686b?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/ede71ae86b38c64bcf00417fd17a686b?s=96&d=mm&r=g","caption":"Coman Cosmin"},"description":"Cosmin Coman is a technology writer and developer with over 3 years of experience. Apart from writing for Kinsta, he has assisted in research at nuclear physics facilities and universities. Tech-savvy and integrated into the community, he always comes up with innovative solutions.","url":"https:\/\/kinsta.com\/es\/blog\/author\/comancosmin\/"}]}},"acf":[],"_links":{"self":[{"href":"https:\/\/kinsta.com\/es\/wp-json\/wp\/v2\/posts\/66683","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kinsta.com\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kinsta.com\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kinsta.com\/es\/wp-json\/wp\/v2\/users\/267"}],"replies":[{"embeddable":true,"href":"https:\/\/kinsta.com\/es\/wp-json\/wp\/v2\/comments?post=66683"}],"version-history":[{"count":15,"href":"https:\/\/kinsta.com\/es\/wp-json\/wp\/v2\/posts\/66683\/revisions"}],"predecessor-version":[{"id":67657,"href":"https:\/\/kinsta.com\/es\/wp-json\/wp\/v2\/posts\/66683\/revisions\/67657"}],"alternate":[{"embeddable":true,"hreflang":"en","title":"English","href":"https:\/\/kinsta.com\/es\/wp-json\/kinsta\/v1\/posts\/66683\/translations\/en"},{"embeddable":true,"hreflang":"it","title":"Italian","href":"https:\/\/kinsta.com\/es\/wp-json\/kinsta\/v1\/posts\/66683\/translations\/it"},{"embeddable":true,"hreflang":"pt","title":"Portuguese","href":"https:\/\/kinsta.com\/es\/wp-json\/kinsta\/v1\/posts\/66683\/translations\/pt"},{"embeddable":true,"hreflang":"fr","title":"French","href":"https:\/\/kinsta.com\/es\/wp-json\/kinsta\/v1\/posts\/66683\/translations\/fr"},{"embeddable":true,"hreflang":"de","title":"German","href":"https:\/\/kinsta.com\/es\/wp-json\/kinsta\/v1\/posts\/66683\/translations\/de"},{"embeddable":true,"hreflang":"ja","title":"Japanese","href":"https:\/\/kinsta.com\/es\/wp-json\/kinsta\/v1\/posts\/66683\/translations\/jp"},{"embeddable":true,"hreflang":"es","title":"Spanish","href":"https:\/\/kinsta.com\/es\/wp-json\/kinsta\/v1\/posts\/66683\/translations\/es"},{"embeddable":true,"hreflang":"nl","title":"Dutch","href":"https:\/\/kinsta.com\/es\/wp-json\/kinsta\/v1\/posts\/66683\/translations\/nl"},{"href":"https:\/\/kinsta.com\/es\/wp-json\/kinsta\/v1\/posts\/66683\/tree"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/kinsta.com\/es\/wp-json\/wp\/v2\/media\/66684"}],"wp:attachment":[{"href":"https:\/\/kinsta.com\/es\/wp-json\/wp\/v2\/media?parent=66683"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kinsta.com\/es\/wp-json\/wp\/v2\/tags?post=66683"},{"taxonomy":"topic","embeddable":true,"href":"https:\/\/kinsta.com\/es\/wp-json\/wp\/v2\/topic?post=66683"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}