Join us at MongoDB.local London on 7 May to unlock new possibilities for your data. Use WEB50 to save 50%.
Register now >
Docs Menu
Docs Home
/ /

Relaciones de modelos en Eloquent

Cuando se usa una base de datos relacional, el siguiente ORM almacena los modelos como filas en tablas que corresponden a las clases de modelo. Cuando usas MongoDB, la Integración de Laravel almacena los modelos como documentos en colecciones que corresponden a las clases de modelos.

Para definir una relación, agregue una función a la clase modelo que llame al método de relación correspondiente. Esta función le permite acceder al modelo relacionado como una propiedad dinámica. Una propiedad dinámica te permite acceder al modelo relacionado utilizando la misma sintaxis que utilizas para acceder a una propiedad en el modelo.

Las siguientes secciones describen las relaciones específicas de Laravel Eloquent y MongoDB disponibles en la Integración de Laravel y muestran ejemplos de cómo definirlas y utilizarlas:

  • Relación uno a uno, creada utilizando el hasOne() el método y su inverso, belongsTo()

  • Una relación de uno a muchos, creada al utilizar el hasMany() y su inverso, belongsTo()

  • Relación muchos a muchos, creada utilizando el método belongsToMany()

  • Patrón de documento incrustado, una relación específica de MongoDB que puede representar una relación uno a uno o uno a muchos, creada mediante el uso del método embedsOne() o embedsMany()

  • Relaciones entre bases de datos cruzadas, requeridas cuando se desea crear relaciones entre modelos de MongoDB y SQL

Una relación uno a uno entre modelos consiste en un registro de modelo relacionado con exactamente otro tipo de registro de modelo.

Cuando agregas una relación uno a uno, Eloquent te permite acceder al modelo mediante una propiedad dinámica y almacena el ID del documento del modelo en el modelo relacionado.

En Laravel MongoDB, puedes definir una relación uno a uno utilizando el método hasOne() o el método belongsTo().

Cuando agregas el inverso de la relación usando el método belongsTo(), Eloquent te permite acceder al modelo usando una propiedad dinámica, pero no agrega ningún campo.

Para aprender más sobre relaciones uno a uno, consulta Uno a uno en la documentación de Laravel.

La siguiente clase de ejemplo muestra cómo definir una relación uno-a-uno HasOne entre un modelo Planet y Orbit usando el método hasOne():

<?php
declare(strict_types=1);
namespace App\Models;
use MongoDB\Laravel\Eloquent\Model;
use MongoDB\Laravel\Relations\HasOne;
class Planet extends Model
{
protected $connection = 'mongodb';
public function orbit(): HasOne
{
return $this->hasOne(Orbit::class);
}
}

La siguiente clase de ejemplo muestra cómo definir la relación inversa BelongsTo entre Orbit y Planet mediante el método belongsTo():

<?php
declare(strict_types=1);
namespace App\Models;
use MongoDB\Laravel\Eloquent\Model;
use MongoDB\Laravel\Relations\BelongsTo;
class Orbit extends Model
{
protected $connection = 'mongodb';
public function planet(): BelongsTo
{
return $this->belongsTo(Planet::class);
}
}

El siguiente código de ejemplo muestra cómo crear una instancia de un modelo para cada clase y añadir la relación entre ellas. Haz clic en el VIEW OUTPUT botón para ver los datos creados ejecutando el código:

$planet = new Planet();
$planet->name = 'Earth';
$planet->diameter_km = 12742;
$planet->save();
$orbit = new Orbit();
$orbit->period = 365.26;
$orbit->direction = 'counterclockwise';
$planet->orbit()->save($orbit);
// Document in the "planets" collection
{
_id: ObjectId('65de67fb2e59d63e6d07f8b8'),
name: 'Earth',
diameter_km: 12742,
// ...
}
// Document in the "orbits" collection
{
_id: ObjectId('65de67fb2e59d63e6d07f8b9'),
period: 365.26,
direction: 'counterclockwise',
planet_id: '65de67fb2e59d63e6d07f8b8',
// ...
}

El siguiente código de ejemplo muestra cómo acceder a los modelos relacionados utilizando las propiedades dinámicas según se definen en las clases de ejemplo:

$planet = Planet::first();
$relatedOrbit = $planet->orbit;
$orbit = Orbit::first();
$relatedPlanet = $orbit->planet;

Una relación de uno a muchos entre modelos consiste en un modelo que es el padre y uno o más registros de modelos secundarios relacionados.

Al añadir un método de relación uno a muchos, Eloquent permite acceder al modelo mediante una propiedad dinámica y almacena el ID de documento del modelo padre en cada documento de modelo secundario.

En Laravel MongoDB, puede definir una relación de uno a muchos añadiendo el método hasMany() en la clase principal y, opcionalmente, el método belongsTo() en la clase secundaria.

Cuando sumas la inversa de la relación usando el método belongsTo(), Eloquent te permite acceder al modelo principal usando una propiedad dinámica sin añadir ningún campo.

Para aprender más sobre las relaciones de uno a muchos, consulta Uno a Muchos en la documentación de Laravel.

La siguiente clase de ejemplo muestra cómo definir una relación HasMany de uno a muchos entre un Planet modelo padre y Moon modelo hijo mediante el método hasMany():

<?php
declare(strict_types=1);
namespace App\Models;
use MongoDB\Laravel\Eloquent\Model;
use MongoDB\Laravel\Relations\HasMany;
class Planet extends Model
{
protected $connection = 'mongodb';
public function moons(): HasMany
{
return $this->hasMany(Moon::class);
}
}

La siguiente clase de ejemplo muestra cómo definir la relación inversa BelongsTo entre un modelo hijo Moon y el modelo padre Planet utilizando el método belongsTo():

<?php
declare(strict_types=1);
namespace App\Models;
use MongoDB\Laravel\Eloquent\Model;
use MongoDB\Laravel\Relations\BelongsTo;
class Moon extends Model
{
protected $connection = 'mongodb';
public function planet(): BelongsTo
{
return $this->belongsTo(Planet::class);
}
}

El siguiente código de ejemplo muestra cómo instanciar un modelo para cada clase y agregar la relación entre ellas. Haz clic en el botón VIEW OUTPUT para ver los datos creados al ejecutar el código:

$planet = new Planet();
$planet->name = 'Jupiter';
$planet->diameter_km = 142984;
$planet->save();
$moon1 = new Moon();
$moon1->name = 'Ganymede';
$moon1->orbital_period = 7.15;
$moon2 = new Moon();
$moon2->name = 'Europa';
$moon2->orbital_period = 3.55;
$planet->moons()->save($moon1);
$planet->moons()->save($moon2);
// Parent document in the "planets" collection
{
_id: ObjectId('65dfb0050e323bbef800f7b2'),
name: 'Jupiter',
diameter_km: 142984,
// ...
}
// Child documents in the "moons" collection
[
{
_id: ObjectId('65dfb0050e323bbef800f7b3'),
name: 'Ganymede',
orbital_period: 7.15,
planet_id: '65dfb0050e323bbef800f7b2',
// ...
},
{
_id: ObjectId('65dfb0050e323bbef800f7b4'),
name: 'Europa',
orbital_period: 3.55,
planet_id: '65dfb0050e323bbef800f7b2',
// ...
}
]

El siguiente código de ejemplo muestra cómo acceder a los modelos relacionados utilizando las propiedades dinámicas tal como se define en las clases de ejemplo.

$planet = Planet::first();
$relatedMoons = $planet->moons;
$moon = Moon::first();
$relatedPlanet = $moon->planet;

Una relación de muchos a muchos consiste en una relación entre dos tipos de modelos diferentes en la que, para cada tipo de modelo, una instancia del modelo puede estar relacionada con múltiples instancias del otro tipo.

En Laravel MongoDB, puedes definir una relación de muchos a muchos añadiendo el método belongsToMany() a ambas clases relacionadas.

Cuando defines una relación de muchos a muchos en una base de datos relacional, Laravel crea una tabla intermedia para rastrear las relaciones. Cuando utilizas la Integración de Laravel, se omite la creación de la tabla intermedia y se agregan los IDs de los documentos relacionados a un campo de documento derivado del nombre de la clase del modelo relacionado.

Tip

Dado que la integración de Laravel utiliza un campo de documento en lugar de una tabla pivote, omite el parámetro tabla pivote del constructor belongsToMany() o establécelo como null.

Para obtener más información sobre relaciones muchos a muchos en Laravel, consulte Muchos a muchos en la documentación de Laravel.

La siguiente sección muestra un ejemplo de cómo crear una relación de muchos a muchos entre clases de modelos.

La siguiente clase de ejemplo muestra cómo definir una relación de BelongsToMany muchos a muchos entre un modelo Planet y SpaceExplorer mediante el método belongsToMany():

<?php
declare(strict_types=1);
namespace App\Models;
use MongoDB\Laravel\Eloquent\Model;
use MongoDB\Laravel\Relations\BelongsToMany;
class Planet extends Model
{
protected $connection = 'mongodb';
public function visitors(): BelongsToMany
{
return $this->belongsToMany(SpaceExplorer::class);
}
}

La siguiente clase de ejemplo muestra cómo definir la relación inversa BelongsToMany de varios a varios entre los modelos SpaceExplorer y Planet usando el método belongsToMany():

<?php
declare(strict_types=1);
namespace App\Models;
use MongoDB\Laravel\Eloquent\Model;
use MongoDB\Laravel\Relations\BelongsToMany;
class SpaceExplorer extends Model
{
protected $connection = 'mongodb';
public function planetsVisited(): BelongsToMany
{
return $this->belongsToMany(Planet::class);
}
}

El siguiente código de ejemplo muestra cómo instanciar un modelo para cada clase y agregar la relación entre ellas. Haz clic en el botón VIEW OUTPUT para ver los datos creados al ejecutar el código:

$planetEarth = new Planet();
$planetEarth->name = 'Earth';
$planetEarth->save();
$planetMars = new Planet();
$planetMars->name = 'Mars';
$planetMars->save();
$planetJupiter = new Planet();
$planetJupiter->name = 'Jupiter';
$planetJupiter->save();
$explorerTanya = new SpaceExplorer();
$explorerTanya->name = 'Tanya Kirbuk';
$explorerTanya->save();
$explorerMark = new SpaceExplorer();
$explorerMark->name = 'Mark Watney';
$explorerMark->save();
$explorerJeanluc = new SpaceExplorer();
$explorerJeanluc->name = 'Jean-Luc Picard';
$explorerJeanluc->save();
$explorerTanya->planetsVisited()->attach($planetEarth);
$explorerTanya->planetsVisited()->attach($planetJupiter);
$explorerMark->planetsVisited()->attach($planetEarth);
$explorerMark->planetsVisited()->attach($planetMars);
$explorerJeanluc->planetsVisited()->attach($planetEarth);
$explorerJeanluc->planetsVisited()->attach($planetMars);
$explorerJeanluc->planetsVisited()->attach($planetJupiter);
// Documents in the "planets" collection
[
{
_id: ObjectId('65e1043a5265269a03078ad0'),
name: 'Earth',
// ...
space_explorer_ids: [
'65e1043b5265269a03078ad3',
'65e1043b5265269a03078ad4',
'65e1043b5265269a03078ad5'
],
},
{
_id: ObjectId('65e1043a5265269a03078ad1'),
name: 'Mars',
// ...
space_explorer_ids: [ '65e1043b5265269a03078ad4', '65e1043b5265269a03078ad5' ]
},
{
_id: ObjectId('65e1043b5265269a03078ad2'),
name: 'Jupiter',
// ...
space_explorer_ids: [ '65e1043b5265269a03078ad3', '65e1043b5265269a03078ad5' ]
}
]
// Documents in the "space_explorers" collection
[
{
_id: ObjectId('65e1043b5265269a03078ad3'),
name: 'Tanya Kirbuk',
// ...
planet_ids: [ '65e1043a5265269a03078ad0', '65e1043b5265269a03078ad2' ]
},
{
_id: ObjectId('65e1043b5265269a03078ad4'),
name: 'Mark Watney',
// ...
planet_ids: [ '65e1043a5265269a03078ad0', '65e1043a5265269a03078ad1' ]
},
{
_id: ObjectId('65e1043b5265269a03078ad5'),
name: 'Jean-Luc Picard',
// ...
planet_ids: [
'65e1043a5265269a03078ad0',
'65e1043a5265269a03078ad1',
'65e1043b5265269a03078ad2'
]
}
]

El siguiente código de ejemplo muestra cómo acceder a los modelos relacionados utilizando las propiedades dinámicas tal como se define en las clases de ejemplo.

$planet = Planet::first();
$explorers = $planet->visitors;
$spaceExplorer = SpaceExplorer::first();
$explored = $spaceExplorer->planetsVisited;

En MongoDB, el patrón de documento incrustado añade los datos del modelo relacionado al modelo padre en lugar de mantener referencias de claves externas. Usa este patrón para cumplir uno o más de los siguientes requisitos:

  • Mantener los datos asociados juntos en una sola colección

  • Realizar actualizaciones atómicas en varios campos del documento y los datos asociados

  • Reducir la cantidad de lecturas requeridas para obtener los datos

En Laravel MongoDB, puedes definir documentos incrustados añadiendo uno de los siguientes métodos:

  • embedsOne() para incrustar un solo documento

  • embedsMany() para insertar múltiples documentos

Nota

Estos métodos devuelven colecciones de Eloquent, que difieren de los objetos del generador de consultas.

Al acceder a una relación incrustada, la integración de Laravel devuelve los datos incrustados como objetos sin procesar en lugar de instancias de modelos hidratadas por defecto. Cuando los documentos incrustados se devuelven como objetos sin procesar, se aplican los siguientes comportamientos:

  • El campo id es de tipo ObjectId, no una cadena.

  • Los campos de fecha son objetos UTCDateTime, no cadenas formateadas.

  • Las conversiones de atributos del modelo, los métodos y la serialización toArray() no se aplican.

Para recuperar los documentos incrustados como instancias de modelo hidratadas, agregue el nombre de la relación a la propiedad $with del modelo padre. Esta propiedad carga automáticamente la relación en cada consulta, de modo que la integración de Laravel hidrata los documentos incrustados como instancias de modelo.

El siguiente ejemplo define un modelo User que utiliza $with para cargar su relación addresses incrustada:

<?php
declare(strict_types=1);
namespace App\Models;
use MongoDB\Laravel\Eloquent\Model;
use MongoDB\Laravel\Relations\EmbedsMany;
class User extends Model
{
protected $with = ['addresses'];
public function addresses()
{
return $this->embedsMany(Address::class);
}
}

Debido a que el modelo incluye $with = ['addresses'], la integración de Laravel devuelve las direcciones incrustadas como instancias del modelo Address. El método toArray() serializa el campo id como una cadena y los campos de fecha como cadenas formateadas. Todas las conversiones y métodos del modelo Address también están disponibles.

Para obtener más información sobre el patrón de documentos incrustados de MongoDB, consulta los siguientes tutoriales de MongoDB Server:

La siguiente sección muestra un ejemplo de cómo utilizar el patrón de documento incrustado.

La siguiente clase de ejemplo muestra cómo definir un EmbedsMany de uno a muchos entre un modelo SpaceShip y Cargo utilizando el método embedsMany():

<?php
declare(strict_types=1);
namespace App\Models;
use MongoDB\Laravel\Eloquent\Model;
use MongoDB\Laravel\Relations\EmbedsMany;
class SpaceShip extends Model
{
protected $connection = 'mongodb';
protected $with = ['cargo'];
public function cargo(): EmbedsMany
{
return $this->embedsMany(Cargo::class);
}
}

La clase de modelo incrustado omite la definición de relación como se muestra en la siguiente clase de modelo Cargo:

<?php
declare(strict_types=1);
namespace App\Models;
use MongoDB\Laravel\Eloquent\Model;
class Cargo extends Model
{
protected $connection = 'mongodb';
}

El siguiente código de ejemplo muestra cómo crear un modelo de SpaceShip e integrar varios modelos de Cargo, y también incluye el documento de MongoDB creado al ejecutar el código. Haz clic en el botón VIEW OUTPUT para ver los datos generados al ejecutar el código:

$spaceship = new SpaceShip();
$spaceship->name = 'The Millenium Falcon';
$spaceship->save();
$cargoSpice = new Cargo();
$cargoSpice->name = 'spice';
$cargoSpice->weight = 50;
$cargoHyperdrive = new Cargo();
$cargoHyperdrive->name = 'hyperdrive';
$cargoHyperdrive->weight = 25;
$spaceship->cargo()->attach($cargoSpice);
$spaceship->cargo()->attach($cargoHyperdrive);
// Document in the "space_ships" collection
{
_id: ObjectId('65e207b9aa167d29a3048853'),
name: 'The Millenium Falcon',
// ...
cargo: [
{
name: 'spice',
weight: 50,
// ...
_id: ObjectId('65e207b9aa167d29a3048854')
},
{
name: 'hyperdrive',
weight: 25,
// ...
_id: ObjectId('65e207b9aa167d29a3048855')
}
]
}

Una relación entre bases de datos cruzadas en Laravel MongoDB es una relación entre modelos almacenados en una base de datos relacional y modelos almacenados en una base de datos MongoDB.

Cuando añades una relación entre bases de datos, Eloquent te permite acceder a los modelos relacionados mediante una propiedad dinámica.

La integración de Laravel admite los siguientes métodos de relación entre bases de datos:

  • hasOne()

  • hasMany()

  • belongsTo()

Para definir una relación entre bases de datos, debe importar el paquete MongoDB\Laravel\Eloquent\HybridRelations en la clase almacenada en la base de datos relacional.

La siguiente sección muestra un ejemplo de cómo definir una relación entre bases de datos.

La siguiente clase de ejemplo muestra cómo definir una relación HasMany entre un modelo SpaceShip almacenado en una base de datos relacional y un modelo Passenger almacenado en una base de datos MongoDB:

<?php
declare(strict_types=1);
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use MongoDB\Laravel\Eloquent\HybridRelations;
class SpaceShip extends Model
{
use HybridRelations;
protected $connection = 'sqlite';
public function passengers(): HasMany
{
return $this->hasMany(Passenger::class);
}
}

La siguiente clase de ejemplo muestra cómo definir la relación inversa BelongsTo entre un modelo Passenger y el modelo Spaceship utilizando el método belongsTo():

<?php
declare(strict_types=1);
namespace App\Models;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use MongoDB\Laravel\Eloquent\Model;
class Passenger extends Model
{
protected $connection = 'mongodb';
public function spaceship(): BelongsTo
{
return $this->belongsTo(SpaceShip::class);
}
}

Tip

Asegúrese de que la llave primaria definida en el esquema de la tabla de su base de datos relacional coincida con la que utiliza su modelo. Para obtener más información sobre llaves primarias y definiciones de esquemas en Laravel, consulta las siguientes páginas en la documentación de Laravel:

El siguiente código de ejemplo muestra cómo crear un modelo SpaceShip en una base de datos MySQL y modelos Passenger relacionados en una base de datos MongoDB, así como los datos creados al ejecutar el código. Haz clic en el botón VIEW OUTPUT para ver los datos creados al ejecutar el código:

$spaceship = new SpaceShip();
$spaceship->id = 1234;
$spaceship->name = 'Nostromo';
$spaceship->save();
$passengerEllen = new Passenger();
$passengerEllen->name = 'Ellen Ripley';
$passengerDwayne = new Passenger();
$passengerDwayne->name = 'Dwayne Hicks';
$spaceship->passengers()->save($passengerEllen);
$spaceship->passengers()->save($passengerDwayne);
-- Row in the "space_ships" table
+------+----------+
| id | name |
+------+----------+
| 1234 | Nostromo |
+------+----------+
// Document in the "passengers" collection
[
{
_id: ObjectId('65e625e74903fd63af0a5524'),
name: 'Ellen Ripley',
space_ship_id: 1234,
// ...
},
{
_id: ObjectId('65e625e74903fd63af0a5525'),
name: 'Dwayne Hicks',
space_ship_id: 1234,
// ...
}
]

Volver

Clase de modelo Eloquent

En esta página