文档菜单
文档首页
/ / /
Laravel MongoDB
/

Eloquent 模型类

本页内容

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

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

以下部分解释了如何将Laravel Eloquent ORM行为添加到Laravel MongoDB模型中

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

  • 扩展Authenticatable模型展示了如何设置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 控制台的信息,请参阅 Laravel 文档中的 Artisan 控制台

要了解如何指定 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 身份验证用户提供者,请参阅 Laravel 文档中的 添加自定义用户提供者

本节展示了如何进行以下Eloquent模型行为自定义

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

注意

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

以下示例指定了自定义MongoDB集合名称 celestial_body,用于 Planet

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

要了解更多关于主键行为和自定义选项的信息,请参阅Laravel文档中的Eloquent Primary Keys

要了解关于_id字段、ObjectIDs以及MongoDB文档结构的信息,请参阅服务器手册中的Documents

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

要了解关于启用了软删除的模型可以执行的方法,请参阅Laravel文档中的Eloquent Soft Deleting

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

在以下示例中,转换助手将存储在 MongoDB 中的 discovery_dt 模型属性,将其从 MongoDB\\BSON\\UTCDateTime 类型转换为 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 模型上的转换助手查询三年前发现的行星的 Laravel 查询

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

注意

Carbon 日期类

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

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

要了解更多关于Laravel类型转换辅助函数和支持的类型,请参阅Laravel文档中的属性转换部分:

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

批量赋值可以是一种创建多个模型的效率很高的方法。然而,它可能会暴露可利用的安全漏洞。字段中的数据可能包含导致未授权权限或访问的更新。

Eloquent 提供以下特质来保护您的数据免受批量赋值漏洞的侵害

  • $fillable 包含在批量赋值中可写入的字段

  • $guarded 包含在批量赋值中忽略的字段

重要

我们建议使用 $fillable 代替 $guarded 以防止漏洞。想了解更多关于此建议的信息,请参阅 Laravel 网站上的 安全发布:Laravel 6.18.35, 7.24.0 文章。

以下示例中,模型通过使用 $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 字段,因为从 $fillable 属性中省略了 day_length

要了解如何更改尝试填充省略在 $fillable 数组中的字段时的行为,请参阅 Laravel 文档中的 批量赋值异常

您可以使用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

有关修剪功能的更多信息,请参阅 Laravel 文档中的 修剪模型

以下可修剪类包含一个 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 模型