Docs 菜单
Docs 主页
/ / /
Laravel MongoDB
/

Eloquent 模型类

在此页面上

  • Overview
  • 定义 Eloquent 模型类
  • 扩展可验证模型
  • 自定义 Eloquent 模型类
  • 更改模型集合名称
  • 更改主键字段
  • 启用软删除
  • 转换数据类型
  • 自定义批量分配
  • 扩展第三方模型类
  • 扩展类示例
  • 指定修剪行为
  • 可修剪示例
  • 批量可修剪示例
  • 创建版本化模型模式
  • 模式版本控制示例

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

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

  • 定义 Eloquent 模型类演示了如何创建模型类。

  • 扩展可验证模型展示了如何将 MongoDB 设置为身份验证用户提供者。

  • 自定义 Eloquent 模型类解释了几种模型类自定义。

  • 扩展第三方模型类解释了如何使第三方模型类与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 控制台Docs 。

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

要将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集合中。

要自定义唯一标识 MongoDB 文档的模型的主键字段,请覆盖模型类的$primaryKey属性。

默认,该模型使用PHP MongoDB驾驶员为 Laravel应用程序插入的每个文档生成唯一的 ObjectID。

以下示例将name字段指定为Planet类的主键:

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

要了解有关主键行为和自定义选项的更多信息,请参阅 Eloquent 主键 在 LaravelDocs 中。

要学习;了解有关_id字段、ObjectID 和MongoDB文档结构的更多信息,请参阅服务器手册中的文档

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

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

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

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

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

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

<?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 v 5.0开始, UTCDateTimeMongoDB中的 BSON值以 Carbon 形式返回 查询结果中的日期类。Laravel 集成在执行此转换时会应用默认时区。

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

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

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

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

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

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

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

重要

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

在以下示例中,模型允许使用$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 作为数据库的模型,请在模型中添加相应的导入:

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

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

注意

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

  • MongoDB\Laravel\Eloquent\SoftDeletes

  • MongoDB\Laravel\Eloquent\MassPrunable

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

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

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

以下批量可修剪类包含一个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,
}
]

后退

Eloquent 模型