jpc / mongodb-odm
一个小巧的MongoDB ODM
Requires
- php: >=5.5
- doctrine/annotations: ^1.4|^1.6
- doctrine/cache: ^1.6|^1.7|^1.8
- mongodb/mongodb: ^1.4
Requires (Dev)
- phpunit/phpunit: ^5.7|^7.4
- symfony/var-dumper: ^3.4|^4.1
README
JPC\MongoDB-ODM 是一个智能的 MongoDB-PHP 映射器。它允许您将 PHP 对象映射到 MongoDB 文档中。此库支持最新的 mongodb 驱动程序,可在以下链接找到:这里。
有关更多详细信息,请参阅 'doc' 文件夹。
安装
使用 Composer 安装
在您的控制台终端
php composer.phar require jpc/mongodb-odm:^1.3
或在您的 composer.json
文件中
{ "require" : { "jpc/mongodb-odm" : "^1.3" } }
创建映射类
您的类
要使用 MongoDB-ODM,您需要将您的类视为一个 mongoDb 文档,并定义您所需的内容
- 一个 id
- 一些字段
您可以创建一个简单的对象,如下所示
<?php namespace ACME\Model; class MyDoc { private $id; private $field1 private $field2; //GETTERS AND SETTERS }
好了,您已经有了您的类。现在您必须告诉 MongoDB-ODM 哪个属性对应哪个字段,以及哪个集合文档(和将要存储的文档)
映射
为此,MongoDB-ODM 使用注解。在 JPC\MongoDB\ODM\Annotations\Mapping
中有一些基本的注解,可以用于创建映射
Document
:定义集合信息Id
:定义将匹配 mongoDb_id
字段的属性Field
:定义字段映射
现在,按照如下方式编辑您的对象
<?php namespace ACME\Model; use JPC\MongoDB\ODM\Annotations\Mapping as ODM; /** * @ODM\Document("my_collection") */ class MyDoc { /** * @ODM\Id */ private $id; /** * @ODM\Field('my_first_field') */ private $field1 /** * @ODM\Field('my_second_field') */ private $field2; //GETTERS AND SETTERS }
高级映射
好了,您有一个简单的文档,但它仍然缺少一些东西...也许像嵌入式文档这样的东西。别担心,MongoDB-ODM 支持!
创建嵌入式类
<?php namespace ACME\Model; use JPC\MongoDB\ODM\Annotations\Mapping as ODM; class MyEmbedded { /** * @ODM\Field('one_field_emb') */ private $oneFieldEmb /** * @ODM\Field('two_field_emb') */ private $twoFieldEmb; //GETTERS AND SETTERS }
现在,您可以使用两个注解在先前的类中添加嵌入式文档
EmbeddedDocument
:嵌入指定类型的文档MultiEmbeddedDocument
:嵌入指定类型的文档数组
按照如下方式修改类 MyDoc
<?php namespace ACME\Model; use JPC\MongoDB\ODM\Annotations\Mapping as ODM; /** * @ODM\Document("my_collection") */ class MyDoc { /** * @ODM\Id */ private $id; /** * @ODM\Field('my_first_field') */ private $field1 /** * @ODM\Field('my_second_field') */ private $field2; /** * @ODM\Field('my_embedded_document') * @ODM\EmbeddedDocument('ACME\Model\MyEmbedded') */ private $myEmbedded; //GETTERS AND SETTERS }
获取文档
获取文档管理器
您可以使用库中提供的工厂轻松地创建文档管理器。
工厂有一个名为 createDocumentManager
的方法,该方法接受 mongo uri 作为第一个参数,数据库名称作为第二个参数。
现在,创建一个文档管理器
<?php use JPC\MongoDB\ODM\Factory\DocumentManagerFactory; $factory = new DocumentManagerFactory(); $factory->createDocumentManager("mongodb://user:password@myserver.com:27017/authdb", "my_db");
获取仓库
现在,您需要获取仓库。仓库将允许您从 MongoDB 获取文档。
要获取仓库,请使用文档管理器的 getRepository
方法。
这是该方法
public function getRepository($modelName, $collection = null)
如果 $collection
为 null,MongoDB-ODM 将使用模型中设置的 Document
注解中的集合
在我们的案例中(在 2-创建映射类
中配置的模型)
<?php [...] $repository = $documentManager->getRepository("ACME\Model\MyDoc");
现在,您可以通过使用仓库的这些函数之一简单地查找文档(有关方法的更多信息,请参阅方法声明)
public function find($id, $projections = [], $options = []); public function findAll($projections = [], $sorts = [], $options = []); public function findBy($filter, $projections = [], $sorts = [], $options = []); public function findOneBy($filter = [], $projections = [], $sorts = [], $options = []); public function findAndModifyOneBy($filter = [], $update = [], $projections = [], $sorts = [], $options = []);
示例
<?php [...] $repository = $documentManager->getRepository("ACME\Model\MyDoc"); // NOTE: filter, projections, etc... can be property name or field name $myDocument = $repository->findOneBy(["field1" => "my_field_value", "myEmbedded.oneFieldEmb" => "another_value"]);
插入、更新或删除文档
插入文档
首先,您必须创建您的对象并在其中插入数据
$obj = new MyDoc(); $obj->setField1("MyValue"); $obj->setField2("MySecondValue");
很好!现在我们想要将其存储在数据库中。为此,您必须告诉 MongoDB-ODM 您的对象需要由它管理。这里的 manage
意味着 MongoDB-ODM 将查看是否需要插入、更新或删除您的对象。
所以,要这样做,您需要 persist
您的对象。
这是文档管理器的 persist
函数
public function persist($object, $collection = null);
对于我们的对象
$documentManager->persist($obj);
下一步是告诉 MongoDB-ODM 需要保存所有管理对象的所有更改。为此,有一个名为 flush
的函数,只需调用它即可。
$documentManager->flush();
检查你的 mongoDb 集合,如果它是空的,你可能犯了一个错误 😕
更新文档
想象一下,你的集合中有许多文档,你只想更新其中的一些。
首先,你必须获取你想要的文档,如下所示
$repo = $documentManager->getRepository("ACME\Model\MyDoc"); $docs = $repo->findBy(["field_1" => "value"])
注意:如果你使用
persist
和flush
插入了一个文档,它已经准备好更新,你不需要再次从仓库中获取它
现在对它们进行一些修改
foreach($docs as $index => $doc){ $doc->setField2($index); }
这是一个非常棒的修改 😉
现在你只需要 flush
。
注意:从仓库中找到的对象已经持久化,你不需要再次持久化
$documentManager->flush();
删除文档
删除就像更新一样简单
从仓库获取你的文档,然后告诉文档管理器要删除它们并刷新
foreach($docs as $doc){ $documentManager->remove($doc); } $documentManager->flush();
附加信息
使用 MongoDB-ODM 更新的优点
使用 MongoDB-ODM 进行更新的优点是它只会更新修改过的字段,而不是整个对象。
取消持久化
如果你在代码中对已持久化的对象进行了一些修改,并且你不想在下次刷新时存储更改,你可以使用 unpersist
函数取消持久化
$documentManager->unpersist($obj);
如果你想取消持久化所有对象,请使用 clear
$documentManager->clear();
GridFS 文档
为 GridFS 文档创建映射
你的类需要继承类 JPC\MongoDB\ODM\GridFS\Document
。该类定义了 GridFS 文档的所有默认字段,如 md5
、filename
等。有关更多详细信息,请参阅此类。
要向你的文档添加元数据,你需要使用 Metadata
注解。
以下是一个示例
namespace ACME\Model; use JPC\MongoDB\ODM\Annotations\Mapping as ODM; use JPC\MongoDB\ODM\GridFS\Annotations\Mapping as GFS; use JPC\MongoDB\ODM\GridFS\Document; /** * @GFS\Document("my_gridfs_bucket") */ class MyGridFSDoc extends Document { /** * @ODM\Field('my_meta_1') * @GFS\Metadata */ private $meta1; }
请注意,类
Document
注解是由GFS
而不是由ODM
命名空间提供的
插入文档
在 GridFS 中插入文档就像在基本 mongoDB 集合中插入文档一样。
以下是一个完整的示例
$doc = new MyGridFSDoc(); $doc->setId("my_super_id") $doc->setFilename("my_file.txt"); $doc->setContentType("text/plain"); $doc->setMeta1("my_value"); $doc->setStream(fopen("my_file.txt", 'r')); $documentManager->persist($doc); $documentManager->flush();
集合选项
集合选项
当你创建模型时,你可以在 Document
注解中指定更多关于模型的信息
<?php namespace ACME\Model; use JPC\MongoDB\ODM\Annotations\Mapping as ODM; /** * @ODM\Document( * "my_collection", * "repositoryClass"="MyCustomRepositoryClass", * "hydratorClass"="MyCustomHydratorClass", * "capped"=true, * "size"=536900000, * "max"=1000 * ) */ class MyDoc { //... }
并且你可以使用 Option
注解设置 ReadConcern、ReadPreference、TypeMap 和 WriteConcern(别忘了使用)
<?php namespace ACME\Model; use JPC\MongoDB\ODM\Annotations\Mapping as ODM; use JPC\MongoDB\ODM\Annotations\CollectionOption as CO; /** * @ODM\Document(//...) * @ODM\Option( * readConcern=@CO\ReadConcern("local"), * readPreference=@CO\ReadPreference( * \MongoDB\Driver\ReadPreference::RP_PRIMARY_PREFERRED, * tagset={{"dc"="ny"}} * ), * typeMap={ * "root"="array", * "array"="array", * "document"="array" * }, * writeConcern=@CO\WriteConcern( * w="majority", * timeout=500, * journal=false * ) * ) */ class MyDoc { //... }
事件
可用事件
如何使用
要向你的模型类添加事件,你需要告诉 ODM 你想要使用一些事件,通过使用 HasLifecycleCallbacks
注解
<?php namespace ACME\Model; use JPC\MongoDB\ODM\Annotations\Mapping as ODM; use JPC\MongoDB\ODM\Annotations\Event; /** * @ODM\Document("my_collection") * @Event\HasLifecycleCallbacks */ class MyDoc { //... }
现在你可以添加一些带有事件注解的方法
<?php namespace ACME\Model; use JPC\MongoDB\ODM\Annotations\Mapping as ODM; use JPC\MongoDB\ODM\Annotations\Event; /** * @ODM\Document("my_collection") * @Event\HasLifecycleCallbacks */ class MyDoc { //... /** * @Event\PreFlush */ public function updateTimestamp(){ $this->date = time(); } }