Docs Menu
Docs Home
/ / /
Laravel MongoDB
/

Eloquent Model Class

On this page

  • Overview
  • Define an Eloquent Model Class
  • Extend the Authenticatable Model
  • Customize an Eloquent Model Class
  • Change the Model Collection Name
  • Change the Primary Key Field
  • Enable Soft Deletes
  • Cast Data Types
  • Customize Mass Assignment
  • Extend Third-Party Model Classes
  • Extended Class Example
  • Specify Pruning Behavior
  • Prunable Example
  • Mass Prunable Example
  • Create a Versioned Model Schema
  • Schema Versioning Example

This guide shows you how to use Laravel MongoDB to define and customize Laravel Eloquent models. You can use these models to work with MongoDB data by using the Laravel Eloquent object-relational mapper (ORM).

The following sections explain how to add Laravel Eloquent ORM behaviors to Laravel MongoDB models:

  • Define an Eloquent Model Class demonstrates how to create a model class.

  • Extend the Authenticatable Model shows how to set MongoDB as the authentication user provider.

  • Customize an Eloquent Model Class explains several model class customizations.

  • Extend Third-Party Model Classes explains how to make third-party model classes compatible with MongoDB.

  • Specify Pruning Behavior shows how to periodically remove models that you no longer need.

  • Create a Versioned Model Schema shows how to implement model schema versioning.

Eloquent models are classes that represent your data. They include methods that perform database operations such as inserts, updates, and deletes.

To declare a Laravel MongoDB model, create a class in the app/Models directory of your Laravel application that extends MongoDB\Laravel\Eloquent\Model as shown in the following code example:

<?php
namespace App\Models;
use MongoDB\Laravel\Eloquent\Model;
class Planet extends Model
{
}

By default, the model uses the MongoDB database name set in your Laravel application's config/database.php setting and the snake case plural form of your model class name for the collection.

This model is stored in the planets MongoDB collection.

Tip

Alternatively, use the artisan console to generate the model class and change the Illuminate\Database\Eloquent\Model import to MongoDB\Laravel\Eloquent\Model. To learn more about the artisan console, see Artisan Console in the Laravel docs.

To learn how to specify the database name that your Laravel application uses, Configure Your MongoDB Connection.

To configure MongoDB as the Laravel user provider, you can extend the Laravel Integration MongoDB\Laravel\Auth\User class. The following code example shows how to extend this class:

<?php
namespace App\Models;
use MongoDB\Laravel\Auth\User as Authenticatable;
class User extends Authenticatable
{
}

To learn more about customizing a Laravel authentication user provider, see Adding Custom User Providers in the Laravel docs.

This section shows how to perform the following Eloquent model behavior customizations:

By default, the model uses the snake case plural form of your model class name. To change the name of the collection the model uses to retrieve and save data in MongoDB, override the $table property of the model class.

Note

We recommend using the default collection naming behavior to keep the associations between models and collections straightforward.

The following example specifies the custom MongoDB collection name, celestial_body, for the Planet class:

<?php
namespace App\Models;
use MongoDB\Laravel\Eloquent\Model;
class Planet extends Model
{
protected $table = 'celestial_body';
}

Without overriding the $table property, this model maps to the planets collection. With the overridden property, the example class stores the model in the celestial_body collection.

To customize the model's primary key field that uniquely identifies a MongoDB document, override the $primaryKey property of the model class.

By default, the model uses the PHP MongoDB driver to generate unique ObjectIDs for each document your Laravel application inserts.

The following example specifies the name field as the primary key for the Planet class:

<?php
namespace App\Models;
use MongoDB\Laravel\Eloquent\Model;
class Planet extends Model
{
protected $primaryKey = 'name';
}

To learn more about primary key behavior and customization options, see Eloquent Primary Keys in the Laravel docs.

To learn more about the _id field, ObjectIDs, and the MongoDB document structure, see Documents in the Server manual.

Eloquent includes a soft delete feature that changes the behavior of the delete() method on a model. When soft delete is enabled on a model, the delete() method marks a document as deleted instead of removing it from the database. It sets a timestamp on the deleted_at field to exclude it from retrieve operations automatically.

To enable soft deletes on a class, add the MongoDB\Laravel\Eloquent\SoftDeletes trait as shown in the following code example:

<?php
namespace App\Models;
use MongoDB\Laravel\Eloquent\Model;
use MongoDB\Laravel\Eloquent\SoftDeletes;
class Planet extends Model
{
use SoftDeletes;
}

To learn about methods you can perform on models with soft deletes enabled, see Eloquent Soft Deleting in the Laravel docs.

Eloquent lets you convert model attribute data types before storing or retrieving data by using a casting helper. This helper is a convenient alternative to defining equivalent accessor and mutator methods on your model.

In the following example, the casting helper converts the discovery_dt model attribute, stored in MongoDB as a MongoDB\\BSON\\UTCDateTime type, to the Laravel datetime type.

<?php
namespace App\Models;
use MongoDB\Laravel\Eloquent\Model;
class Planet extends Model
{
protected $casts = [
'discovery_dt' => 'datetime',
];
}

Tip

Casts in Laravel 11

In Laravel 11, you can define a casts() method to specify data type conversions instead of using the $casts attribute. The following code performs the same conversion as the preceding example by using a casts() method:

protected function casts(): array
{
return [
'discovery_dt' => 'datetime',
];
}

To learn more, see Attribute Casting in the Laravel documentation.

This conversion lets you use the PHP DateTime class to work with dates in this field. The following example shows a Laravel query that uses the casting helper on the model to query for planets with a discovery_dt of less than three years ago:

Planet::where( 'discovery_dt', '>', new DateTime('-3 years'))->get();

Note

Carbon Date Class

Starting in Laravel MongoDB v5.0, UTCDateTime BSON values in MongoDB are returned as Carbon date classes in query results. The Laravel Integration applies the default timezone when performing this conversion.

To learn more about MongoDB's data types, see BSON Types in the Server manual.

To learn more about the Laravel casting helper and supported types, see Attribute Casting in the Laravel docs.

Eloquent lets you create several models and their attribute data by passing an array of data to the create() model method. This process of inserting multiple models is called mass assignment.

Mass assignment can be an efficient way to create multiple models. However, it can expose an exploitable security vulnerability. The data in the fields might contain updates that lead to unauthorized permissions or access.

Eloquent provides the following traits to protect your data from mass assignment vulnerabilities:

  • $fillable contains the fields that are writeable in a mass assignment

  • $guarded contains the fields that are ignored in a mass assignment

Important

We recommend using $fillable instead of $guarded to protect against vulnerabilities. To learn more about this recommendation, see the Security Release: Laravel 6.18.35, 7.24.0 article on the Laravel site.

In the following example, the model allows mass assignment of the fields by using the $fillable attribute:

<?php
namespace App\Models;
use MongoDB\Laravel\Eloquent\Model;
class Planet extends Model
{
protected $fillable = [
'name',
'gravitational_force',
'diameter',
'moons',
];
}

The following code example shows mass assignment of the Planet model:

$planets = [
[ 'name' => 'Earth', 'gravitational_force' => 9.8, 'day_length' => '24 hours' ],
[ 'name' => 'Mars', 'gravitational_force' => 3.7, 'day_length' => '25 hours' ],
];
Planet::create($planets);

The models saved to the database contain only the name and gravity fields since day_length is omitted from the $fillable attribute.

To learn how to change the behavior when attempting to fill a field omitted from the $fillable array, see Mass Assignment Exceptions in the Laravel docs.

You can use the Laravel Integration to extend a third-party model class by including the DocumentModel trait when defining your model class. By including this trait, you can make the third-party class compatible with MongoDB.

When you apply the DocumentModel trait to a model class, you must set the $keyType property to 'string' as the Laravel Integration casts MongoDB ObjectId values to type string.

This example creates a Planet model class that extends the CelestialBody class from a package called ThirdPartyPackage. The Post class includes the DocumentModel trait and defines properties including $primaryKey and $keyType:

<?php
namespace App\Models;
use MongoDB\Laravel\Eloquent\DocumentModel;
use ThirdPartyPackage\CelestialBody;
class Planet extends CelestialBody
{
use DocumentModel;
protected $fillable = ['name', 'diameter'];
protected $keyType = 'string';
}

After defining your class, you can perform MongoDB operations as usual.

Tip

To view another example that uses the DocumentModel trait, see the Laravel Sanctum section of the User Authentication guide.

Eloquent lets you specify criteria to periodically delete model data that you no longer need. When you schedule or run the model:prune command, Laravel calls the prunable() method on all models that import the Prunable and MassPrunable traits to match the models for deletion.

To use this feature with models that use MongoDB as a database, add the appropriate import to your model:

  • MongoDB\Laravel\Eloquent\Prunable optionally performs a cleanup step before deleting a model that matches the criteria

  • MongoDB\Laravel\Eloquent\MassPrunable deletes models that match the criteria without fetching the model data

Note

When enabling soft deletes on a mass prunable model, you must import the following Laravel MongoDB packages:

  • MongoDB\Laravel\Eloquent\SoftDeletes

  • MongoDB\Laravel\Eloquent\MassPrunable

To learn more about the pruning feature, see Pruning Models in the Laravel docs.

The following prunable class includes a prunable() method that matches models that the prune action deletes and a pruning() method that runs before deleting a matching model:

<?php
namespace App\Models;
use MongoDB\Laravel\Eloquent\Model;
use MongoDB\Laravel\Eloquent\Prunable;
class Planet extends Model
{
use Prunable;
public function prunable()
{
// matches models in which the solar_system field contains a null value
return static::whereNull('solar_system');
}
protected function pruning()
{
// Add cleanup actions, such as logging the Planet 'name' attribute
}
}

The following mass prunable class includes a prunable() method that matches models that the prune action deletes:

<?php
namespace App\Models;
use MongoDB\Laravel\Eloquent\MassPrunable;
use MongoDB\Laravel\Eloquent\Model;
class Planet extends Model
{
use MassPrunable;
public function prunable()
{
// matches models in which the gravitational_force field contains
// a value greater than 0.5
return static::where('gravitational_force', '>', 0.5);
}
}

You can implement a schema versioning pattern into your application by using the HasSchemaVersion trait on an Eloquent model. You might choose to implement a schema version to organize or standardize a collection that contains data with different schemas.

Tip

To learn more about schema versioning, see the Model Data for Schema Versioning tutorial in the Server manual.

To use this feature with models that use MongoDB as a database, add the MongoDB\Laravel\Eloquent\HasSchemaVersion import to your model. Then, set the SCHEMA_VERSION constant to 1 to set the first schema version on your collection. If your collection evolves to contain multiple schemas, you can update the value of the SCHEMA_VERSION constant in subsequent model classes.

When creating your model, you can define the migrateSchema() method to specify a migration to the current schema version upon retrieving a model. In this method, you can specify the changes to make to an older model to update it to match the current schema version.

When you save a model that does not have a schema version specified, the HasSchemaVersion trait assumes that it follows the latest schema version. When you retrieve a model that does not contain the schema_version field, the trait assumes that its schema version is 0 and performs the migration.

In this sample situation, you are working with a collection that was first modeled by the following class:

<?php
namespace App\Models;
use MongoDB\Laravel\Eloquent\Model;
class Planet extends Model
{
protected $fillable = ['name', 'type'];
}

Now, you want to implement a new schema version on the collection. You can define the new model class with the following behavior:

  • Implements the HasSchemaVersion trait and sets the current SCHEMA_VERSION to 2

  • Defines the migrateSchema() method to migrate models in which the schema version is less than 2 to have a galaxy field that has a value of 'Milky Way'

<?php
namespace App\Models;
use MongoDB\Laravel\Eloquent\HasSchemaVersion;
use MongoDB\Laravel\Eloquent\Model;
class Planet extends Model
{
use HasSchemaVersion;
public const SCHEMA_VERSION = 2;
protected $fillable = ['name', 'type', 'galaxy'];
/**
* Migrate documents with a lower schema version to the most current
* schema when inserting new data or retrieving from the database.
*/
public function migrateSchema(int $fromVersion): void
{
if ($fromVersion < 2) {
$this->galaxy = 'Milky Way';
}
}
}

In the "WASP-39 b" document in the following code, the schema_version field value is less than 2. When you retrieve the document, the Laravel Integration adds the galaxy field and updates the schema version to the current version, 2.

The "Saturn" document does not contain the schema_version field, so the Laravel Integration assigns it the current schema version upon saving.

Finally, the code retrieves the models from the collection to demonstrate the changes:

// Simulates a document in the collection with schema version 1
Planet::insert([
[
'name' => 'WASP-39 b',
'type' => 'gas',
'schema_version' => 1,
],
]);
// Saves a document with no specified schema version
$saturn = Planet::create([
'name' => 'Saturn',
'type' => 'gas',
]);
// Retrieves both models from the collection
$planets = Planet::where('type', 'gas')
->get();
[
{
"_id": ...,
"name": "WASP-39 b",
"type": "gas",
"galaxy": "Milky Way",
"schema_version": 2,
},
{
"_id": ...,
"name": "Saturn",
"type": "gas",
"schema_version": 2,
}
]

Back

Eloquent Models