Overview
Al usar una base de datos relacional, el ORM de Eloquent almacena los modelos como filas en tablas que corresponden a las clases del modelo. Al usar MongoDB, la integración de Laravel almacena los modelos como documentos en colecciones que corresponden a las clases del modelo.
Para definir una relación, agregue una función a la clase del modelo que llame al método de relación correspondiente. Esta función permite acceder al modelo relacionado como una propiedad dinámica. Una propiedad dinámica permite acceder al modelo relacionado utilizando la misma sintaxis que se utiliza para acceder a una propiedad del 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 usarlas:
Relación uno a uno, creada mediante el uso de
hasOne()método y su inverso,belongsTo()Relación de uno a muchos, creada mediante el uso de
hasMany()y su inverso,belongsTo()Relación de muchos a muchos, creada mediante el
belongsToMany()métodoPatrón de documento incrustado, una relación específica de MongoDB que puede representar una relación de uno a uno o de uno a muchos, creada mediante el
embedsOne()embedsMany()método oRelaciones entre bases de datos, necesarias cuando se desea crear relaciones entre modelos MongoDB y SQL
Relación uno a uno
Una relación uno a uno entre modelos consiste en un registro de modelo relacionado con exactamente otro tipo de registro de modelo.
Cuando agrega una relación uno a uno, Eloquent le 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 agrega la inversa de la relación mediante el método belongsTo(), Eloquent le permite acceder al modelo mediante una propiedad dinámica, pero no agrega ningún campo.
Para obtener más información sobre las relaciones uno a uno, consulte Uno a uno en la documentación de Laravel.
Ejemplo uno a uno
La siguiente clase de ejemplo muestra cómo definir una relación uno a uno HasOne entre un modelo Planet y Orbit utilizando el método hasOne():
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 utilizando el método belongsTo():
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 instanciar un modelo para cada clase y agregar la relación entre ellos. Haga clic en el botón VIEW OUTPUT Botón para ver los datos creados al ejecutar 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 mediante el uso de las propiedades dinámicas definidas en las clases de ejemplo:
$planet = Planet::first(); $relatedOrbit = $planet->orbit; $orbit = Orbit::first(); $relatedPlanet = $orbit->planet;
Relación de uno a muchos
Una relación de uno a muchos entre modelos consta de un modelo que es el padre y uno o más registros de modelos secundarios relacionados.
Cuando agrega un método de relación de uno a muchos, Eloquent le permite acceder al modelo mediante una propiedad dinámica y almacena el ID del documento del modelo principal en cada documento del modelo secundario.
En Laravel MongoDB, puedes definir una relación de uno a muchos agregando el método hasMany() en la clase principal y, opcionalmente, el método belongsTo() en la clase secundaria.
Cuando agrega la inversa de la relación mediante el método belongsTo(), Eloquent le permite acceder al modelo principal mediante una propiedad dinámica sin agregar ningún campo.
Para obtener más información sobre las relaciones de uno a muchos, consulte Uno a muchos en la documentación de Laravel.
Ejemplo de uno a muchos
La siguiente clase de ejemplo muestra cómo definir una relación de uno a muchos HasMany entre un modelo padre Planet y un modelo hijo Moon utilizando el método hasMany():
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 secundario Moon y el modelo principal Planet utilizando el método belongsTo():
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 muestra muestra cómo acceder a los modelos relacionados mediante el uso de las propiedades dinámicas definidas en las clases de ejemplo.
$planet = Planet::first(); $relatedMoons = $planet->moons; $moon = Moon::first(); $relatedPlanet = $moon->planet;
Relación de muchos a muchos
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 relacionarse con múltiples instancias del otro tipo.
En Laravel MongoDB, puedes definir una relación de muchos a muchos agregando el método belongsToMany() a ambas clases relacionadas.
Al definir una relación de muchos a muchos en una base de datos relacional, Laravel crea una tabla dinámica para rastrear las relaciones. Al usar la integración de Laravel, se omite la creación de la tabla dinámica y se añaden los ID de los documentos relacionados a un campo de documento derivado del nombre de la clase del modelo correspondiente.
Tip
Dado que la integración de Laravel utiliza un campo de documento en lugar de una tabla dinámica, omita el parámetro de tabla dinámica del constructor belongsToMany() o configúrelo en 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 modelo.
Ejemplo de muchos a muchos
La siguiente clase de ejemplo muestra cómo definir una relación de muchos a muchos BelongsToMany entre un modelo Planet y SpaceExplorer utilizando el método belongsToMany():
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 muchos a muchos entre un modelo SpaceExplorer y Planet utilizando el método belongsToMany():
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 muestra muestra cómo acceder a los modelos relacionados mediante el uso de las propiedades dinámicas definidas en las clases de ejemplo.
$planet = Planet::first(); $explorers = $planet->visitors; $spaceExplorer = SpaceExplorer::first(); $explored = $spaceExplorer->planetsVisited;
Patrón de Documento Incrustado
En MongoDB, el patrón de documento incrustado añade los datos del modelo relacionado al modelo principal en lugar de conservar las referencias de claves foráneas. Utilice 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 múltiples campos del documento y los datos asociados
Reducir la cantidad de lecturas necesarias para obtener los datos
En Laravel MongoDB, puedes definir documentos incrustados agregando uno de los siguientes métodos:
embedsOne()para incrustar un solo documentoembedsMany()para incrustar varios documentos
Nota
Estos métodos devuelven colecciones de Eloquent, que difieren de los objetos del generador de consultas.
Hidratación automática
Al usar un patrón de documento incrustado, la integración de Laravel recupera todos los datos incrustados del documento, a menos que se usen los métodos de construcción de consultas select() o project(). Los datos incrustados no se hidratan automáticamente en las instancias del modelo. Para hidratar automáticamente los objetos incrustados, use la propiedad $with al definir las relaciones.
El siguiente ejemplo de código demuestra cómo utilizar la propiedad $with para hidratar automáticamente objetos incrustados:
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); } }
Para obtener más información sobre el patrón de documento incrustado de MongoDB, consulte los siguientes tutoriales de MongoDB Server:
La siguiente sección muestra un ejemplo de cómo utilizar el patrón de documento incrustado.
Ejemplo de documento incrustado
La siguiente clase de ejemplo muestra cómo definir una relación de uno a muchos EmbedsMany entre un modelo SpaceShip y Cargo utilizando el método embedsMany():
declare(strict_types=1); namespace App\Models; use MongoDB\Laravel\Eloquent\Model; use MongoDB\Laravel\Relations\EmbedsMany; class SpaceShip extends Model { protected $connection = 'mongodb'; public function cargo(): EmbedsMany { return $this->embedsMany(Cargo::class); } }
La clase de modelo incorporada omite la definición de relación como se muestra en la siguiente clase de modelo Cargo:
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 SpaceShip e incrustar varios modelos Cargo y el documento MongoDB creado al ejecutar el código. Haga clic en el botón VIEW OUTPUT para ver los datos creados 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') } ] }
Relaciones entre bases de datos
Una relación entre bases de datos 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 agrega una relación entre bases de datos, Eloquent le 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.
Ejemplo de 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:
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():
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 clave principal 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 las claves principales y las definiciones de esquema de Laravel, consulte las siguientes páginas de 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, // ... } ]