Eloquent Model Relationships
On this page
Overview
When you use a relational database, the Eloquent ORM stores models as rows in tables that correspond to the model classes. When you use MongoDB, the Laravel Integration stores models as documents in collections that correspond to the model classes.
To define a relationship, add a function to the model class that calls the appropriate relationship method. This function allows you to access the related model as a dynamic property. A dynamic property lets you access the related model by using the same syntax as you use to access a property on the model.
The following sections describe the Laravel Eloquent and MongoDB-specific relationships available in the Laravel Integration and show examples of how to define and use them:
One to one relationship, created by using the
hasOne()
method and its inverse,belongsTo()
One to many relationship, created by using the
hasMany()
and its inverse,belongsTo()
Many to many relationship, created by using the
belongsToMany()
methodEmbedded document pattern, a MongoDB-specific relationship that can represent a one to one or one to many relationship, created by using the
embedsOne()
orembedsMany()
methodCross-database relationships, required when you want to create relationships between MongoDB and SQL models
One to One Relationship
A one to one relationship between models consists of a model record related to exactly one other type of model record.
When you add a one to one relationship, Eloquent lets you access the model by using a dynamic property and stores the model's document ID on the related model.
In Laravel MongoDB, you can define a one to one relationship by using the
hasOne()
method or belongsTo()
method.
When you add the inverse of the relationship by using the belongsTo()
method, Eloquent lets you access the model by using a dynamic property, but
does not add any fields.
To learn more about one to one relationships, see One to One in the Laravel documentation.
One to One Example
The following example class shows how to define a HasOne
one to one
relationship between a Planet
and Orbit
model by using the
hasOne()
method:
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); } }
The following example class shows how to define the inverse BelongsTo
relationship between Orbit
and Planet
by using the belongsTo()
method:
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); } }
The following sample code shows how to instantiate a model for each class and add the relationship between them. Click the VIEW OUTPUT button to see the data created by running the code:
$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', // ... }
The following sample code shows how to access the related models by using the dynamic properties as defined in the example classes:
$planet = Planet::first(); $relatedOrbit = $planet->orbit; $orbit = Orbit::first(); $relatedPlanet = $orbit->planet;
One to Many Relationship
A one to many relationship between models consists of a model that is the parent and one or more related child model records.
When you add a one to many relationship method, Eloquent lets you access the model by using a dynamic property and stores the parent model's document ID on each child model document.
In Laravel MongoDB, you can define a one to many relationship by adding the
hasMany()
method on the parent class and, optionally, the belongsTo()
method on the child class.
When you add the inverse of the relationship by using the belongsTo()
method, Eloquent lets you access the parent model by using a dynamic property
without adding any fields.
To learn more about one to many relationships, see One to Many in the Laravel documentation.
One to Many Example
The following example class shows how to define a HasMany
one to many
relationship between a Planet
parent model and Moon
child model by
using the hasMany()
method:
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); } }
The following example class shows how to define the inverse BelongsTo
relationship between a Moon
child model and the and the Planet
parent
model by using the belongsTo()
method:
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); } }
The following sample code shows how to instantiate a model for each class and add the relationship between them. Click the VIEW OUTPUT button to see the data created by running the code:
$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', // ... } ]
The following sample code shows how to access the related models by using the dynamic properties as defined in the example classes.
$planet = Planet::first(); $relatedMoons = $planet->moons; $moon = Moon::first(); $relatedPlanet = $moon->planet;
Many to Many Relationship
A many to many relationship consists of a relationship between two different model types in which, for each type of model, an instance of the model can be related to multiple instances of the other type.
In Laravel MongoDB, you can define a many to many relationship by adding the
belongsToMany()
method to both related classes.
When you define a many to many relationship in a relational database, Laravel creates a pivot table to track the relationships. When you use the Laravel Integration, it omits the pivot table creation and adds the related document IDs to a document field derived from the related model class name.
Tip
Since the Laravel Integration uses a document field instead of a pivot table, omit
the pivot table parameter from the belongsToMany()
constructor or set
it to null
.
To learn more about many to many relationships in Laravel, see Many to Many in the Laravel documentation.
The following section shows an example of how to create a many to many relationship between model classes.
Many to Many Example
The following example class shows how to define a BelongsToMany
many to
many relationship between a Planet
and SpaceExplorer
model by using
the belongsToMany()
method:
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); } }
The following example class shows how to define the inverse BelongsToMany
many to many relationship between a SpaceExplorer
and Planet
model by
using the belongsToMany()
method:
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); } }
The following sample code shows how to instantiate a model for each class and add the relationship between them. Click the VIEW OUTPUT button to see the data created by running the code:
$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' ] } ]
The following sample code shows how to access the related models by using the dynamic properties as defined in the example classes.
$planet = Planet::first(); $explorers = $planet->visitors; $spaceExplorer = SpaceExplorer::first(); $explored = $spaceExplorer->planetsVisited;
Embedded Document Pattern
In MongoDB, the embedded document pattern adds the related model's data into the parent model instead of keeping foreign key references. Use this pattern to meet one or more of the following requirements:
Keeping associated data together in a single collection
Performing atomic updates on multiple fields of the document and the associated data
Reducing the number of reads required to fetch the data
In Laravel MongoDB, you can define embedded documents by adding one of the following methods:
embedsOne()
to embed a single documentembedsMany()
to embed multiple documents
Note
These methods return Eloquent collections, which differ from query builder objects.
To learn more about the MongoDB embedded document pattern, see the following MongoDB Server tutorials:
The following section shows an example of how to use the embedded document pattern.
Embedded Document Example
The following example class shows how to define an EmbedsMany
one to many
relationship between a SpaceShip
and Cargo
model by using the
embedsMany()
method:
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); } }
The embedded model class omits the relationship definition as shown in the
following Cargo
model class:
declare(strict_types=1); namespace App\Models; use MongoDB\Laravel\Eloquent\Model; class Cargo extends Model { protected $connection = 'mongodb'; }
The following sample code shows how to create a SpaceShip
model and
embed multiple Cargo
models and the MongoDB document created by running the
code. Click the VIEW OUTPUT button to see the data created by
running the code:
$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') } ] }
Cross-Database Relationships
A cross-database relationship in Laravel MongoDB is a relationship between models stored in a relational database and models stored in a MongoDB database.
When you add a cross-database relationship, Eloquent lets you access the related models by using a dynamic property.
The Laravel Integration supports the following cross-database relationship methods:
hasOne()
hasMany()
belongsTo()
To define a cross-database relationship, you must import the
MongoDB\Laravel\Eloquent\HybridRelations
package in the class stored in
the relational database.
The following section shows an example of how to define a cross-database relationship.
Cross-Database Relationship Example
The following example class shows how to define a HasMany
relationship
between a SpaceShip
model stored in a relational database and a
Passenger
model stored in a MongoDB database:
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); } }
The following example class shows how to define the inverse BelongsTo
relationship between a Passenger
model and the and the Spaceship
model by using the belongsTo()
method:
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
Make sure that the primary key defined in your relational database table schema matches the one that your model uses. To learn more about Laravel primary keys and schema definitions, see the following pages in the Laravel documentation:
The following sample code shows how to create a SpaceShip
model in
a MySQL database and related Passenger
models in a MongoDB database as well
as the data created by running the code. Click the VIEW OUTPUT button
to see the data created by running the code:
$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, // ... } ]