trismegiste / yuurei
Requires
- php: >=5.5
- ext-mongo: >=1.5.0
- trismegiste/alkahest: ~2.3
Requires (Dev)
- nikic/php-parser: 0.9.x-dev
This package is not auto-updated.
Last update: 2022-04-12 09:28:09 UTC
README
MongoDB中的原子性由Xzibit解释
什么是
这是一个具有自动映射的微型数据库层。它适用于熟悉并理解无模式数据库上模型增长的MongoDB的高级用户。
当我提到“微型”时,意味着NCLOC的总和小于臭名昭著的方法UnitOfWork::createEntity在Doctrine 2中的大小
当然,功能也是“微型”。不要期望不可能的事情。尽管如此,还有一些你可能在其他地方找不到的功能。
此外,此DBAL可以完全扩展。我的其他存储库DokudokiBundle为symfony2添加了3种额外的映射系统,而无需编写大量代码。
如何
像其他PHP包一样使用Composer
$ composer.phar require trismegiste/yuurei dev-master
为什么
因为,就像蛋糕一样,“ODM是一个谎言”。将MongoDB转换成类似ORM的抽象是最糟糕的事情,你可以在NoSQL数据库上做的事情。
使用ODM,你失去了NoSQL和RDBMS的特性,以下是一些
- MongoDB没有丰富的文档,因为查询生成器很糟糕,映射很复杂
- 没有无模式的能力,因为你在类中冻结了模型
- 没有JOIN,你必须依赖于缓慢的延迟加载
- 没有RDBMS的约束(引用和类型),因为没有这些
- 没有原子性:MongoDB中唯一的原子性是在一个文档上
事实上,ODM是一个缓慢的ORM,没有ACID:使用MongoDB的目的是什么?
这就是为什么我停止追逐“神秘的对象数据库”,并开始破解。
指导
- 丰富的文档由地狱!你有原子性。
- 停止思考1个实体 <=> 1个表
- 只有少量根实体:2、3或4个,最多10个用于完整的电子商务应用,而不是200个!
- 1个应用 <=> 1个集合
- 忘记1NF、2NF和3NF。在MongoDB中处理反规范化数据比在MySQL中进行过多的LEFT JOIN更容易
- 像serialize/unserialize一样思考
- 不要试图用你的数据库创建搜索引擎:使用Elastic Search
- 不要试图将所有内容存储在集合中:使用XML文件
因此,你将模型分成几个部分,没有循环引用,并将其存储起来。这就像序列化,但是在MongoDB中。
所有非静态属性都存储在一种方式中,您可以使用强大的(但坦白说非常奇怪)的MongoDB语言轻松查询。
请参阅PHPUnit测试以获取序列化过程的示例。
这就像序列化
您知道PHP可以使用序列化保存和恢复任何对象到会话中,并且不需要任何映射信息、注释或存储库。这是我开始这个库时的范式。
为什么ORM/ODM不能做同样的事情?当然,我需要一个NoSQL数据库。但这个类似dbal/odm的数据库不需要任何映射信息,存储在数据库中的对象保持其原始结构(没有太多噪音)。因此,您可以使用MongoDB进行复杂查询。
请参阅单元测试中的完整示例。
// simple object $doc = new \Some\Sample\Product('EF-85 L', 2000); // persisting $this->invocation->persist($doc); // restoring with invocation repository $restore = $this->invocation->findByPk((string) $doc->getId()); $this->assertInstanceOf('Some\Sample\Product', $restore); // retrieving the content in the MongoDB $dump = $this->collection->findOne(array('_id' => $doc->getId())); $this->assertEquals('Some\Sample\Product', $dump['-fqcn']); // we store the FQCN $this->assertEquals('EF-85 L', $dump['title']); $this->assertEquals(2000, $dump['price']);
关于MDE
随着最近的NoSQL、SOA和HMVC概念,我认为MDE有些过时了,虽然不是总是这样,但非常频繁。事实上,这并不是MDE本身,而是一个非常常见的反模式:“数据库驱动开发”,其中所有源代码都来自数据库模式。结合CRUD生成器,会导致贫血模型、愚蠢的构造函数和无用的setter/getter(没有业务意义)。
关于性能
待办
常见问题解答
有什么要求?
- PHP >= 5.4
- PECL Mongo扩展 >= 1.3
如何映射属性?
所有对象的属性都将被存储。您只需做一件事:根类必须实现Persistable接口(有一个特质用于实现此接口)。您不需要扩展任何特定类,因此您可以在没有约束的情况下遵循DDD。
什么是“根类”?
这是存储在集合中、其键为'_id'的MongoId的类。此类中的所有其他聚合对象不需要实现Persistable,它们将被递归存储。
有什么约束?
此库无法保存和恢复来自父类的私有属性。持久化类中的私有属性是好的,但它们不会被子类看到,因此如果您将这些子类保存到数据库中,则无法持久化。这是一个很大的限制,所以使用关键字'private'时要小心。
我如何删除一些瞬态属性?
您不能。但您可以使用具有Skippable接口的瞬态类。使用装饰者模式或状态模式。您的模型可以做到这一点。
我可以在持久化之前进行一些清理吗?
类似于序列化,您可以通过实现两个方法来实现Cleanable:唤醒和睡眠。
如何查询列表?
使用MongoCollection,您无法比这个底层层更高效。
如何存储图片或PDF?
在您的模型中使用MongoBinData,它以原样存储。
我可以用MongoId以外的其他东西作为主键吗?
不。当然,MongoDB允许您使用其他内容,但在大多数情况下,这并不是一个好主意。
关于MongoDate呢?
任何DateTime都将转换为MongoDate,反之亦然。
您对这个库使用了哪些指导原则?
- 除了一个接口(用于DDD关注点)之外,模型没有强制性的继承。
- 最小数量的switch,因为它是隐藏的继承。
- 每个类不超过5个方法。
- 没有方法超过20 NCLOC。
- 没有静态方法,因为它是全球性的。
- SRP, OCP, LSP, ISP, DIP 保持在最高水平
- 耦合度保持在最低水平(通过Mondrian 检查)
对于DBRef是否有任何延迟加载或代理类?
飞吧,傻瓜们
“幽霊”的含义是什么?
实际上,这个库是DokudokiBundle的一部分,我想保留这个Bundle中最好的部分,作为一个独立的库。因此,我保留了它的日文名称。幽霊意味着鬼魂或精神,因为在原始的bundle中,这个映射系统被命名为“Invocation”。