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
Overview
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.
Define an Eloquent Model Class
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:
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.
Extend the Authenticatable Model
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:
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.
Customize an Eloquent Model Class
This section shows how to perform the following Eloquent model behavior customizations:
Change the Model Collection Name
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:
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.
Change the Primary Key Field
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:
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.
Enable Soft Deletes
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:
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.
Cast Data Types
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.
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
or the Carbon 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();
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.
Customize Mass Assignment
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:
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.
Extend Third-Party Model Classes
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
declare the following properties in your class:
$primaryKey = '_id'
, because the_id
field uniquely identifies MongoDB documents$keyType = 'string'
, because the Laravel Integration casts MongoDBObjectId
values to typestring
Extended Class Example
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
:
namespace App\Models; use MongoDB\Laravel\Eloquent\DocumentModel; use ThirdPartyPackage\CelestialBody; class Planet extends CelestialBody { use DocumentModel; protected $fillable = ['name', 'diameter']; protected $primaryKey = '_id'; 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.
Specify Pruning Behavior
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 criteriaMongoDB\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.
Prunable Example
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:
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 } }
Mass Prunable Example
The following mass prunable class includes a prunable()
method that matches
models that the prune action deletes:
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); } }
Create a Versioned Model Schema
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.
Schema Versioning Example
In this sample situation, you are working with a collection that was first modeled by the following class:
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 currentSCHEMA_VERSION
to2
Defines the
migrateSchema()
method to migrate models in which the schema version is less than2
to have agalaxy
field that has a value of'Milky Way'
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();