trismegiste/dokudoki

该包已废弃且不再维护。未建议替代包。

无模式数据库层用于MongoDB和无模式功能的辅助工具

安装: 113

依赖: 1

建议者: 0

安全: 0

星级: 4

关注者: 1

分支: 0

开放问题: 1

类型:symfony-bundle

v2.3.2 2015-08-04 08:48 UTC

This package is not auto-updated.

Last update: 2021-11-26 08:19:50 UTC


README

是什么

这是一个基于 Yuurei 的扩展包,Yuurei 是一个具有自动映射的微型数据库层。

除了 Yuurei 的原始映射外,该扩展包还添加了多个功能:3 种其他映射系统(完全魔法、别名和两者的混合)、处理 MongoDate 和上传文件的表单组件、用于 WebProfiler 的 DataCollector,以及当然,许多注入到 symfony2 的 DiC 中的服务。

我试图创建一个无差别的 DBAL,它能够在模型完成与否的情况下帮助您构建应用程序。因此,这里也有迁移工具。

如何使用

像其他 PHP 包一样使用 Composer

对于 Symfony 2.3

    "require": {
        "trismegiste/dokudoki": "dev-master"
    },

Symfony 2.x 的遗留版本

    "require": {
        "trismegiste/dokudoki": "dev-Symfony2.x"
    },

为什么

因为,就像蛋糕一样,“ODM 是一个谎言”。将 MongoDB 转换成类似 ORM 的抽象是您可以对 NoSQL 数据库做的最糟糕的事情。

我对 CRUD 反模式和 ORM 和代码生成器产生的贫血模型感到厌倦。最终,您意识到您必须为 ORM 而不是为业务建模您的类。我想要恢复在 Symfony2 中发展的领域驱动开发哲学,而不是 Doctrine2 破坏的哲学。

指导

  • 丰富的文档 哇!您具有原子性。
  • 停止思考 1 实体 <=> 1 表
  • 只有少数根实体:2、3 或 4,对于完整的电子商务应用程序,最多 10 个!
  • 1 应用 <=> 1 集合
  • 忘记 1NF、2NF 和 3NF。在 MongoDB 中处理反规范化数据比在 MySQL 中处理过多的 LEFT JOIN 更容易。
  • 像 serialize/unserialize 一样思考
  • 不要尝试用您的数据库来复制搜索引擎:使用 Elastic Search
  • 不要尝试在集合中存储所有内容:使用 XML 文件

因此,您将模型分成几个部分,没有循环引用,并将其存储。这就像序列化,但是在 MongoDB 中。

所有非静态属性都以一种方式存储,您可以使用 MongoDB 强大的(但坦白说很奇怪)语言轻松地进行查询。

查看 PHPUnit 测试 以获取示例。

四种工作模式

此 DBAL 有 4 个阶段,根据模型类的完成程度而定。

技巧在于,在开发您的应用程序时,可以在这些阶段之间迁移,例如,在有了脏原型之后不需要从头开始。甚至在没有模型的情况下,您还可以从已存储在集合中的数据生成模型。

请参阅使用此dbal在PHPUnit测试中的示例

黑魔法是黑色的

如果您没有模型并且要设计许多表单,请从“黑魔法”阶段开始。如果您对贫血模型就足够了,就无需创建它。它充满了魔法方法、魔法映射和魔法文档,就像在工作原型。

但请注意:它是用于原型设计的,如果您不小心,数据库可能会反击您。这就是我所说的“表单驱动开发”。

请参阅单元测试中的完整示例

// construct a form
$form = $this->formFactory
        ->createBuilder('magic_form', null, array('class_key' => 'product'))
        ->add('title')
        ->add('price')
        ->getForm();
// bind data to the form
$form->bind(array('title' => 'EF-85 L', 'price' => 2000));
$doc = $form->getData();
// getting the magic document
$this->assertInstanceOf('Trismegiste\DokudokiBundle\Magic\Document', $doc);
$this->assertEquals('product', $doc->getClassName());
$this->assertEquals('EF-85 L', $doc->getTitle());
// persistence with blackmagic repository
$this->blackmagic->persist($doc);
// restoring with blackmagic repository
$restore = $this->blackmagic->findByPk((string) $doc->getId());
$this->assertInstanceOf('Trismegiste\DokudokiBundle\Magic\Document', $restore);
$this->assertEquals('product', $restore->getClassName());
$this->assertEquals('EF-85 L', $restore->getTitle());

序列化可能足够

这是来自Yuurei的原始映射系统。如果您有很多几乎完成模型的类并且不想配置任何内容,请使用“调用”阶段。只有魔法映射和对象与文档之间的严格类型。

但如果您需要执行复杂查询或映射-减少,这可能会非常脏。此阶段对没有GUI的RESTful应用程序非常有用。

请参阅单元测试中的完整示例

// 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']);

白魔法是为正义而存在的

如果您有一个好的模型并且有时间在数据库中仔细别名类,请使用“白魔法”阶段。有自动映射,但不用说,您的模型不能变成混乱。任何未别名的类都会引发异常。

请参阅单元测试中的完整示例

// simple object
$doc = new \Some\Sample\Product('EF-85 L', 2000);
// persisting
$this->whitemagic->persist($doc);
// restoring with whitemagic repository
$restore = $this->whitemagic->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('product', $dump['-class']);  // here is the aliasing
$this->assertEquals('EF-85 L', $dump['title']);
$this->assertEquals(2000, $dump['price']);

Hoodoo 子类

如果您需要进化上述模型,可以使用“Hoodoo”阶段,这是一个“白魔法”阶段,混合了一些来自“黑魔法”阶段的魔法。有一个安全网来防止一些“真实”的类变成“虚假”的类。这降低了每分钟的WTF率,您可以选择魔法级别。

关于性能

我还没有完全测试这个dbal,但是填充是这个层中最慢的部分。例如,一个包含100个实体的文档(考虑一个客户,他的地址,过去的订单和产品等...)在没有APC的标准双核台式机上存储需要大约100毫秒。

它并不非常高效,但当您寻求高性能时,您可能会忘记ORM、ODM等。

常见问题解答

是否必须使用Symfony2?

不,DBAL可以以独立模式工作。无论如何,您会错过许多表单和黑魔法阶段的特性。完整的框架本身不是必需的,只有一些组件。而且几乎所有的单元测试都不需要任何symfony组件。例如,您可以为silex和pimple轻松创建一个提供者。

有什么要求?

  • PHP >= 5.4
  • PECL Mongo扩展 >= 1.3
  • dev-master版本使用Symfony2.3运行,并且有2.1和2.2的分支。

如何映射属性?

所有对象的属性都将被存储。你只需做一件事:根类必须实现Persistable接口(有一个用于实现此接口的特质)。你不需要扩展任何特定的类,因此你可以无约束地遵循DDD。

什么是“根类”?

这是存储在集合中的一个类,它在键'_id'中包含MongoId。此类中所有其他聚合对象不需要实现Persistable,它们将被递归存储。

我如何移除一些瞬态属性?

你无法移除。但你可以有一个实现了Skippable接口的瞬态类。使用装饰器模式或状态模式。你的模型可以做到这一点。

在持久化前我可以做一些清理吗?

像序列化一样,你可以通过实现Cleanable接口的2个方法:wakeup和sleep来实现。

我如何进行查询列表?

使用MongoCollection,你无法比这个底层层更高效。

我如何存储图片或PDF?

在你的模型中使用MongoBinData,它将按原样存储。

我可以使用MongoId之外的其它东西作为主键吗?

不可以。

关于MongoDate呢?

所有DateTime都将转换为MongoDate,反之亦然。

我看到你在你的类模型中使用mongo类型,关于抽象呢?

严肃地说,你有没有将一个应用程序切换到另一个数据库?

对于DBRef有延迟加载或代理类吗?

Fly,你们这些傻瓜。

为什么这个名字这么傻?

嗯,我不擅长找名字,这就是我倾向于保留最荒谬而不是最严肃的原因。它代表Docu(ment) + doki,为了回忆“dokidoki”(在日本语中大致意味着“兴奋”,听起来像心跳)。这个,我相当确信它是独一无二的 ^_^