Docs Menu
Docs Home
/ / /
Laravel MongoDB
/

Eloquent Model Relationships

On this page

  • Overview
  • One to One Relationship
  • One to One Example
  • One to Many Relationship
  • One to Many Example
  • Many to Many Relationship
  • Many to Many Example
  • Embedded Document Pattern
  • Embedded Document Example
  • Cross-Database Relationships
  • Cross-Database Relationship Example

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() method

  • Embedded document pattern, a MongoDB-specific relationship that can represent a one to one or one to many relationship, created by using the embedsOne() or embedsMany() method

  • Cross-database relationships, required when you want to create relationships between MongoDB and SQL models

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.

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:

<?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);
}
}

The following example class shows how to define the inverse BelongsTo relationship between Orbit and Planet by using the belongsTo() method:

<?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);
}
}

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;

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.

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:

<?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);
}
}

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:

<?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);
}
}

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;

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.

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:

<?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);
}
}

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:

<?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);
}
}

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;

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 document

  • embedsMany() 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.

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:

<?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';
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:

<?php
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')
}
]
}

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.

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:

<?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);
}
}

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:

<?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

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,
// ...
}
]

Back

Eloquent Model Class