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

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 模型行为自定义:

默认情况下,模型使用模型类名称的蛇形命名法复数形式。 要更改模型用于在 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类型。

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

重要

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

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

保存到数据库的模型仅包含namegravity字段,因为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 会在导入PrunableMassPrunable特征的所有模型上调用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\Laravel\Eloquent\HasSchemaVersion导入添加到您的模型中。 然后,设立SCHEMA_VERSION常量设置为1 ,以设立集合的第一个模式版本。 如果您的集合发展为包含多个模式,则可以更新后续模型类中SCHEMA_VERSION常量的值。

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

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

在此示例情况下,您正在使用的集合首先由以下类建模:

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

现在,您想要在集合上实现新的模式版本。 您可以使用以下行为定义新的模型类:

  • 实现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 集成在保存时为其分配当前模式版本。

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

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