对于 AI 代理:可在 https://www.mongodb.com/zh-cn/docs/llms.txt 获取文档索引—通过在任何 URL 路径后添加 .md 可获取所有页面的 Markdown 版本。

Eloquent 模型类

本指南向您展示如何使用 Laravel MongoDB来定义和自定义 Laravel Eloquent 模型。 您可以使用这些模型,通过 Laravel Eloquent 对象关系映射器 (ORM) 来处理MongoDB数据。

以下部分介绍如何将 Laravel Eloquent ORM 行为添加到 Laravel MongoDB 模型:

Eloquent 模型是表示数据的类。 其中包括执行插入、更新和删除等数据库操作的方法。

要声明 Laravel MongoDB模型,请在 Laravel应用程序的app/Models目录中创建一个扩展MongoDB\Laravel\Eloquent\Model的类,如以下代码示例:

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

默认,该模型使用 Laravel 应用程序的config/database.php设置中设置的MongoDB 数据库名称以及设立的模型集合名称的蛇形命名复数形式。

此模型存储在planets MongoDB 集合中。

提示

或者,使用 artisan 控制台生成模型类并将 Illuminate\Database\Eloquent\Model 导入更改为 MongoDB\Laravel\Eloquent\Model。要学习;了解有关artisan 控制台的更多信息,请参阅 LaravelDocs中的 Artisan 控制台。

要了解如何指定 Laravel 应用程序使用的数据库名称,请配置您的 MongoDB 连接。

注意

MongoDB始终将主键存储在 _id字段中。该字段在模型中作为 $id 访问。使用查询构建器时,Laravel 集成会将查询中的 id 转换为 _id。这样可以与使用 id字段的其他 Laravel 组件兼容。您可以通过设置模型的 $keyType属性并在保存模型之前赋值来自定义标识符类型。

要将MongoDB配置为 Laravel 用户提供商,您可以扩展 Laravel 集成MongoDB\Laravel\Auth\User类。 以下代码示例展示了如何扩展此类:

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

要学习;了解有关自定义 Laravel身份验证用户提供商的更多信息,请参阅 LaravelDocs中的添加自定义用户提供程序。

本节介绍如何执行以下 Eloquent 模型行为自定义:

注意

Laravel 集合是一个 PHP 类,用于保存模型列表,而 MongoDB 集合则在数据库中存储文档。

默认情况下,模型使用模型类名称的蛇形命名法复数形式。要更改模型用于检索和保存数据的集合名称,请覆盖模型类的 $table 属性。

注意

我们建议使用默认的集合命名行为,以使模型和集合之间的关联保持简单明了。

以下示例为Planet类指定自定义 MongoDB 集合名称celestial_body :

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

在不覆盖$table属性的情况下,该模型映射到planets集合。 使用重写的属性,该示例类将模型存储在celestial_body集合中。

Eloquent 包含软删除功能,可更改模型上delete()方法的行为。 在模型上启用软删除后, delete()方法会将文档标记为已删除,而不是将其从数据库中删除。 它在deleted_at字段上设置时间戳,以自动将其排除在检索操作之外。

要对类启用软删除,请添加Illuminate\Database\Eloquent\SoftDeletes特征,如以下代码示例:

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

要学习;了解可以在启用了软删除的模型上执行的方法,请参阅 LaravelDocs中的 Eloquent 软删除。

Eloquent 允许您在存储或检索数据之前使用转换助手转换模型属性数据类型。 此助手是在模型上定义等效访问器和赋值器方法的便捷替代方法。

在以下示例中,转换助手将 discovery_dt 模型属性(作为MongoDB\\BSON\\UTCDateTime 类型存储在MongoDB中)转换为 Laravel datetime 类型。

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

提示

Laravel 11中的转换

从 Laravel 11 开始,您可以定义 casts() 方法来指定数据类型转换,而不是使用 $casts 属性。以下代码使用 casts() 方法执行与前面的示例相同的转换:

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

要学习;了解更多信息,请参阅 Laravel 文档中的属性转换。

这种转换允许您使用PHP DateTime 类来处理该字段中的日期。以下示例显示了一个 Laravel查询,该查询使用模型上的转换助手来查询discovery_dt 小于三年前的行星:

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

注意

碳日期类

从 Laravel MongoDB v5.0 开始,MongoDB中的 UTCDateTime BSON值在查询结果中作为Carbon 日期类返回。Laravel 集成在执行此转换时会应用默认时区。

要了解有关 MongoDB 数据类型的更多信息,请参阅服务器手册中的 BSON types。

要学习;了解有关 Laravel 转换助手和支持类型的更多信息,请参阅 LaravelDocs中的属性转换。

重要

从 Laravel MongoDB v5.8 开始,array 转换类型已被弃用。使用 array 作为转换类型会将属性值存储为 MongoDB 中的 JSON 编码字符串,这不是原生的 BSON 格式。从 v5.9 开始,您可以改用 AsBsonArray 和 AsBsonDocument 转换类型。要了解更多信息,包括迁移选项,请参阅 版本 5.8 弃用。

以下示例展示了如何在模型的 $casts 属性中使用 AsBsonDocument 和 AsBsonArray 转换类型:

use MongoDB\Laravel\Eloquent\Casts\AsBsonArray;use MongoDB\Laravel\Eloquent\Casts\AsBsonDocument;use MongoDB\Laravel\Eloquent\Model; class BsonCasting extends Model{ protected $connection = 'mongodb'; protected $fillable = ['specs', 'variants']; protected $casts = [ 'specs' => AsBsonDocument::class, 'variants' => AsBsonArray::class, ];}

Eloquent 允许您通过将数据大量传递给create()模型方法来创建多个模型及其属性数据。 这种插入多个模型的进程称为批量分配。

批量分配是创建多个模型的有效方法。 但是,它可能会暴露一个可利用的安全漏洞。 这些字段中的数据可能包含导致未经授权的权限或访问的更新。

Eloquent 提供以下特征来保护您的数据免受批量赋值漏洞的影响:

  • $fillable 包含可在批量分配中写入的字段

  • $guarded 包含在批量分配中忽略的字段

重要

我们建议使用 $fillable 而不是 $guarded 以防范漏洞。要学习;了解有关此建议的更多信息,请参阅安全发布:Laravel 6.18.35、7.24。0 Laravel站点上的文章。

在以下示例中,模型允许使用$fillable属性对字段进行批量分配:

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

以下代码示例显示了Planet模型的批量分配:

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

保存到数据库的模型仅包含name和gravity字段,因为day_length $fillable属性中省略了 。

要学习;了解如何更改尝试填充$fillable 大量中省略的字段时的行为,请参阅 LaravelDocs中的批量赋值异常。

您可以使用 Laravel 集成来扩展第三方模型类,方法是在定义模型类时包含DocumentModel特征。 通过包含此特征,可以使第三方类与MongoDB兼容。

应用DocumentModel特征应用于模型类时,必须设立$keyType属性设置为'string' ,因为 Laravel 集成会将MongoDB ObjectId值转换为类型string 。

此示例创建一个Planet模型类,用于扩展名为ThirdPartyPackage的包中的CelestialBody类。 Post类包含DocumentModel特征,并定义包括$primaryKey和$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';}

定义类后,您可以照常执行MongoDB操作。

提示

要查看使用DocumentModel特征的另一个示例,请参阅 用户身份验证指南的Laravel Sanctum部分。

Eloquent 允许您指定条件以定期删除不再需要的模型数据。 当您安排或运行model:prune命令时,Laravel 会在导入Prunable和MassPrunable特征的所有模型上调用prunable()方法,以匹配要删除的模型。

要将此功能用于使用 MongoDB 作为数据库的模型,请在模型中添加相应的导入:

  • Illuminate\Database\Eloquent\Prunable 在删除符合条件的模型之前,可选择执行清理步骤

  • MongoDB\Laravel\Eloquent\MassPrunable 删除符合条件的模型,而不获取模型数据

注意

在批量可修剪模型上启用软删除时,必须导入以下 Laravel MongoDB包:

  • Illuminate\Database\Eloquent\SoftDeletes

  • MongoDB\Laravel\Eloquent\MassPrunable

要学习;了解有关修剪功能的更多信息,请参阅 LaravelDocs中的修剪模型。

以下可修剪类包括一个用于匹配修剪操作删除的模型的prunable()方法,以及一个在删除匹配模型之前运行的pruning()方法:

<?php namespace App\Models; use MongoDB\Laravel\Eloquent\Model;use Illuminate\Database\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 }}

以下批量可修剪类包含一个prunable()方法,用于匹配修剪操作删除的模型:

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

您可以通过在 Eloquent 模型上使用 HasSchemaVersion 特性,在应用程序中实现模式版本控制模式。您可以选择实现模式版本,以组织或标准化包含不同模式数据的 MongoDB 集合。

提示

要学习;了解有关模式版本控制的更多信息,请参阅服务器手册中的“模式版本控制的数据模型”教程。

要将此功能与使用 MongoDB 作为数据库的模型配合使用,请将 MongoDB\Laravel\Eloquent\HasSchemaVersion 导入添加到您的模型中。然后,将 SCHEMA_VERSION 常量设置为 1,以在您的 MongoDB 集合上设置第一个模式版本。如果集合演变为包含多个模式,您可以在后续模型类中更新 SCHEMA_VERSION 常量的值。

创建模型时,可以定义migrateSchema()方法,指定在检索模型时迁移到当前模式版本。 在此方法中,您可以指定对旧模型进行的更改,以将其更新以匹配当前的模式版本。

当您保存未指定模式版本的模型时, HasSchemaVersion特征假定它遵循最新的模式版本。 当您检索不包含schema_version字段的模型时,该特征假定其模式版本为0并执行迁移。

在此示例场景中,您正在使用一个最初由以下类建模的 MongoDB 集合:

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

现在,您想要在 MongoDB 集合上实现一个新的模式版本。您可以定义具有以下行为的新模型类:

  • 实现HasSchemaVersion特征并将当前的SCHEMA_VERSION设置为2

  • 定义migrateSchema()方法,用于迁移模式版本低于2的模型,使其具有值为'Milky Way'的galaxy字段

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

在以下代码的"WASP-39 b"文档中, schema_version字段值小于2 。 当您检索文档时,Laravel 集成会添加galaxy字段并将模式版本更新为当前版本2 。

"Saturn"文档不包含schema_version字段,因此 Laravel 集成在保存时为其分配当前模式版本。

最后,代码从 MongoDB 集合中检索模型以演示更改:

// Simulates a document in the collection with schema version 1Planet::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();