Dyi*_*yin 8 php mapping object mongodb
引导问题:
class T当我从一个接收它时,构建我的对象的最佳做法是MongoCursor::getNext()什么?就其而言,a的getNext()函数MongoCursor返回array.我希望将该点的结果用作object类型的结果T.
我应该为类型编写自己的构造函数T,它接受一个array?是否存在任何通用解决方案,例如在类型时T extends G,G以递归方式(对于嵌套文档)以常规方式执行作业.
我是MongoDB的新手,我想用一个漂亮的界面构建我自己的通用映射器.
赏金:
这个答案已被重写。
大多数数据映射器的工作方式是为每个类表示一个对象,或者“模型”通常是创造的术语。如果您希望允许通过单个对象(即$model->find())进行多次访问,通常会对其进行分隔,以便该方法实际上不会返回其自身的实例,而是返回数组或MongoCursor急切地将类加载到空间中。
这种范例通常与“Active Record”相关。这是 ORM、ODM 和框架以某种方式与数据库通信的方法,不仅适用于 MongoDB,也适用于 SQL 和任何其他突然出现的数据库(Cassandra、CouchDB 等)。
应该立即注意的是,尽管活动记录提供了很大的功能,但它不应该覆盖整个应用程序。有时直接使用驱动程序会更有利。因此,大多数 ORM、ODM 和框架都提供了快速、轻松地直接访问驱动程序的能力。
正如许多人所说,不存在轻量级数据映射器。如果您要将返回的数据映射到类,那么它将消耗资源,结束。这样做的好处是你在操纵物体时获得的力量。
Active record 非常擅长从 PHP 内部提供事件和触发器。一个很好的例子是我为 Yii 制作的 ORM:https://github.com/Sammaye/MongoYii它可以提供以下钩子:
afterConstructbeforeFindafterFindbeforeValidateafterValidatebeforeSaveafterSave应该注意的是,当涉及到 MongoDB 等事件时,beforeSaveMongoDBafterSave不具备触发器(https://jira.mongodb.org/browse/SERVER-124),因此应用程序应该处理此事件是有意义的。除了应用程序处理此问题的明显原因之外,它还可以通过调用本机 PHP 函数来操作在接触数据库之前保存的每个文档,从而更好地处理保存函数。
大多数数据映射器也使用 PHP 自己的 CRUD 类来表示它们的数据映射器。例如创建一条新记录:
$d=new User();
$d->username='sammaye';
$d->save();
Run Code Online (Sandbox Code Playgroud)
这是一个非常好的方法,因为您创建了一个“新”(https://github.com/Sammaye/MongoYii/blob/master/EMongoDocument.php#L46)类来制作一个新记录“新纪录。它在语义上非常适合。
更新函数通常通过读取函数访问,您无法更新您不知道其存在的模型。这将我们带入填充模型的下一步。
为了处理填充模型,不同的 ORM、ODM 和框架采用不同的方法。例如,我的 MongoYii 扩展使用model每个类中调用的工厂方法来带回其自身的新实例,以便我可以调用动态方法find和findOne其他此类方法。
一些 ORM、ODM 和框架提供读取函数作为直接static函数,使它们本身成为工厂方法,而有些则使用单例模式,但是,我选择不这样做(/sf/answers/321742641/)。
大多数(如果不是全部)都实现某种形式的游标。这用于返回多个模型并直接包装(通常)以返回预填充模型来MongoCursor替换该方法。current()
例如调用:
User::model()->find();
Run Code Online (Sandbox Code Playgroud)
将返回一个(在 MongoYii 中),然后它会存储该类用于实例化光标的EMongoCursor事实,并且在调用时如下所示:User
foreach(User::model() as $k=>$v){
var_dump($v);
}
Run Code Online (Sandbox Code Playgroud)
将在此处调用该current()方法: https: //github.com/Sammaye/MongoYii/blob/master/EMongoCursor.php#L102返回模型的新单个实例。
有一些 ORM、ODM 和框架实现了急切数组加载。这意味着他们只会将整个结果作为模型数组直接加载到您的 RAM 中。我个人不喜欢这种方法,它很浪费,而且当您由于在需要添加到旧记录的地方添加一些新功能而需要使用活动记录进行较大更新时也不是好兆头。
在我继续之前的最后一个主题是 MongoDB 的无模式本质。将 PHP 类与 MongoDB 结合使用的问题是,您需要 PHP 的所有功能,但又需要 MongoDB 的可变特性。这在 SQL 中很容易克服,因为它有一个预定义的模式,您只需查询它并完成工作;然而,MongoDB 没有这样的东西。
这确实使得 MongoDB 中的模式处理变得相当危险。private大多数 ORM、ODM 和框架要求您使用变量get和方法预先定义现场模式(即 Doctrine 2)set。在 MongoYii 中,为了让我的生活变得轻松而优雅,我决定通过使用能够检测的魔法来保留 MongoDB 的无模式本质(https://github.com/Sammaye/MongoYii/blob/master/EMongoModel.php#L26是我的__get,https ://github.com/Sammaye/MongoYii/blob/master/EMongoModel.php#L47是我的__set),如果该属性在类中无法访问,如果该字段位于内部_attributes数组中,如果不是,则返回null。同样,为了设置属性,我只需在内部_attributes变量中设置。
至于如何分配此模式,我将内部分配留给了用户,但是,为了处理表单等的设置属性,我使用了验证规则(https://github.com/Sammaye/MongoYii/blob/master/EMongoModel)。 php#L236)调用一个名为的函数getSafeAttributeNames(),该函数将返回具有针对它们的验证规则的属性列表。如果它们没有验证规则,则不会设置传入$_POST或数组中存在的那些属性。$_GET因此,这提供了模式但安全的模型结构的能力。
我们已经介绍了如何实际使用根文档,您还会问如何数据映射器处理子文档。Doctrine 2 和许多其他提供了完整的基于类的子文档(http://docs.doctrine-project.org/projects/doctrine-mongodb-odm/en/latest/reference/embedded-mapping.html),但这可能非常足智多谋。相反,我决定提供辅助函数,允许灵活使用子文档,而无需急于将它们加载到模型中,从而消耗 RAM。基本上我所做的就是留下它们,因为它们提供了一个验证器(https://github.com/Sammaye/MongoYii/blob/master/validators/ESubdocumentValidator.php)用于在它们内部进行验证。当然,验证器是自生成的,因此如果您在验证器中有一条规则再次使用验证器来发出嵌套子文档的验证,那么它就会起作用。
因此,我认为关于 ORM、ODM 和使用数据映射器的框架的非常基本的讨论已经完成。当然,我可能可以就此写一篇完整的文章,但我相信,就目前而言,这是一个足够好的讨论。
| 归档时间: |
|
| 查看次数: |
1862 次 |
| 最近记录: |