Eloquent 模型类
在此页面上
Overview
本指南向您展示如何使用 Laravel MongoDB来定义和自定义 Laravel Eloquent 模型。 您可以使用这些模型,通过 Laravel Eloquent 对象关系映射器 (ORM) 来处理MongoDB数据。
以下部分介绍如何将 Laravel Eloquent ORM 行为添加到 Laravel MongoDB 模型:
定义 Eloquent 模型类演示了如何创建模型类。
扩展可验证模型展示了如何将 MongoDB 设置为身份验证用户提供者。
自定义 Eloquent 模型类解释了几种模型类自定义。
扩展第三方模型类解释了如何使第三方模型类与MongoDB兼容。
指定修剪行为展示了如何定期删除不再需要的模型。
创建版本化模型模式展示了如何实现模型模式版本控制。
定义 Eloquent 模型类
Eloquent 模型是表示数据的类。 其中包括执行插入、更新和删除等数据库操作的方法。
要声明 Laravel MongoDB 模型,请在 Laravel 应用程序的 app/Models
目录中创建一个扩展MongoDB\Laravel\Eloquent\Model
的类,如以下代码示例所示:
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
类。 以下代码示例展示了如何扩展此类:
namespace App\Models; use MongoDB\Laravel\Auth\User as Authenticatable; class User extends Authenticatable { }
要了解有关自定义 Laravel 身份验证用户提供程序的更多信息,请参阅 添加自定义用户提供程序 在 LaravelDocs 中。
自定义 Eloquent 模型类
本节介绍如何执行以下 Eloquent 模型行为自定义:
更改模型集合名称
默认情况下,模型使用模型类名称的蛇形命名法复数形式。 要更改模型用于在 MongoDB 中检索和保存数据的集合的名称,请覆盖模型类的$table
属性。
注意
我们建议使用默认的集合命名行为,以使模型和集合之间的关联保持简单明了。
以下示例为Planet
类指定自定义 MongoDB 集合名称celestial_body
:
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
类的主键:
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
特征,如以下代码示例:
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
类型。
namespace App\Models; use MongoDB\Laravel\Eloquent\Model; class Planet extends Model { protected $casts = [ 'discovery_dt' => 'datetime', ]; }
提示
Laravel 11中的转换
此转换允许您使用PHP DateTime 类来处理该字段中的日期。以下示例显示了一个 Laravel查询,该查询使用模型上的转换助手来查询discovery_dt
小于三年前的行星:
Planet::where( 'discovery_dt', '>', new DateTime('-3 years'))->get();
注意
碳日期类
从 Laravel MongoDB v 5.0开始, UTCDateTime
MongoDB中的 BSON值以 Carbon 形式返回 查询结果中的日期类。Laravel 集成在执行此转换时会应用默认时区。
要学习;了解有关MongoDB数据类型的更多信息,请参阅服务器手册中的BSON types 。
要了解有关 Laravel 转换助手和支持类型的更多信息,请参阅 属性转换 在 LaravelDocs 中。
自定义批量分配
Eloquent 允许您通过将数据大量传递给create()
模型方法来创建多个模型及其属性数据。 这种插入多个模型的进程称为批量分配。
批量分配是创建多个模型的有效方法。 但是,它可能会暴露一个可利用的安全漏洞。 这些字段中的数据可能包含导致未经授权的权限或访问的更新。
Eloquent 提供以下特征来保护您的数据免受批量赋值漏洞的影响:
$fillable
包含可在批量分配中写入的字段$guarded
包含在批量分配中忽略的字段
重要
我们建议使用$fillable
而不是$guarded
以防范漏洞。 要了解有关此建议的更多信息,请参阅 安全发布:Laravel6.18.35 、7.24 。0Laravel 网站上的文章。
在以下示例中,模型允许使用$fillable
属性对字段进行批量分配:
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
在内的属性:
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 作为数据库的模型,请在模型中添加相应的导入:
MongoDB\Laravel\Eloquent\Prunable
在删除符合条件的模型之前,可选择执行清理步骤MongoDB\Laravel\Eloquent\MassPrunable
删除符合条件的模型,而不获取模型数据
注意
在批量可修剪模型上启用软删除时,必须导入以下 Laravel MongoDB包:
MongoDB\Laravel\Eloquent\SoftDeletes
MongoDB\Laravel\Eloquent\MassPrunable
要学习;了解有关修剪功能的更多信息,请参阅 修剪模型 在 LaravelDocs 中。
可修剪示例
以下可修剪类包括一个用于匹配修剪操作删除的模型的prunable()
方法,以及一个在删除匹配模型之前运行的pruning()
方法:
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()
方法,用于匹配修剪操作删除的模型:
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
并执行迁移。
模式版本控制示例
在此示例情况下,您正在使用的集合首先由以下类建模:
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
字段
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, } ]