2

我正在尝试通过读取文档的元数据来编写一个处理文档序列化的类。我从这个使用 Doctrine ORM 的实体的实现中得到启发,并对其进行了修改以匹配 Doctrine ODM 处理文档的方式。不幸的是,有些东西不能正常工作,因为一个文档永远不会被序列化超过一次,即使它被第二次引用,从而导致不完整的序列化。

例如,它为属于某个 place1(请参阅Place 文档)的 user1(请参阅用户文档)输出此(以 json 格式)。然后它输出位置和属于它的用户,我们应该再次看到 user1 但我们没有:

{
  id: "505cac0d6803fa1e15000004",
  login: "user1",
  places: [
    {
      id: "505cac0d6803fa1e15000005",
      code: "place1",
      users: [
        {
          id: "505c862c6803fa6812000000",
          login: "user2"
        }
      ]
    }
  ]
}

我想这可能与阻止循环引用的东西有关,但有办法解决吗?

另外,我在 ZF2 应用程序中使用它,是否有更好的方法来使用 ZF2 Serializer 来实现它?

谢谢你的帮助。

4

2 回答 2

3

我已经为 DoctrineODM 编写了一个序列化程序。您可以在http://github.com/superdweebie/DoctrineExtensions中找到它- 查看lib/Sds/DoctrineExtensions/Serializer.

如果您使用的是 zf2,那么您可能还喜欢http://github.com/superdweebie/DoctrineExtensionsModule,它配置 DoctrineExtensions 以在 zf2 中使用。

要使用该模块,请使用 composer 安装它,就像安装任何其他模块一样。然后将以下内容添加到您的 zf2 配置中:

'sds' => [
    'doctrineExtensions' => [
        'extensionConfigs' => [
            'Sds\DoctrineExtensions\Serializer' => null,
        ),
    ),
),

要获取序列化程序,请使用:

$serializer = $serivceLocator->get('Sds\DoctrineExtensions\Serializer');

要使用序列化程序:

$array = $serializer->toArray($document)
$json = $serializer->toJson($document)

$document = $serializer->fromArray($array)
$document = $serializer->fromJson($json)

如果您想使用它们,还有一些额外的注释可用于控制序列化:

@Sds\Setter - specify a non standard setter for a property
@Sds\Getter - specify a non standard getter fora  property
@Sds\Serializer(@Sds\Ignore) - ignore a property when serializing

这一切仍在进行中,因此任何评论/改进将不胜感激。当您遇到这些库的问题时,只需将它们记录在 github 上,它们就会得到及时解决。

最后是关于序列化嵌入文档和引用文档的说明 - 嵌入文档应该与其父文档一起序列化,而引用文档不应该。这反映了数据在数据库中的保存方式。这也意味着循环引用不是问题。

更新

我已经将更新推送到 Sds/DoctrineExtensions/Serializer 以便它现在可以正确处理引用。以下三(五)种方法已更新:

toArray/toJson
fromArray/fromJson
applySerializeMetadataToArray

前两个是自我解释的——最后一个是允许应用序列化规则,而不必将数据库结果水合到文档中。

默认情况下,引用将被序列化为这样的数组:

[$ref: 'CollectionName/DocumentId']

引用的$ref风格是 Mongo 内部使用的,所以看起来很合适。给出引用的格式,期望它可以用作 REST API 的 URL。

可以通过定义这样的替代方法来覆盖默认行为ReferenceSerializer

/**
 * @ODM\ReferenceMany(targetDocument="MyTargetDocument")
 * @Sds\Serializer(@Sds\ReferenceSerializer('MyAlternativeSerializer'))
 */
protected $myDocumentProperty;

ReferenceSerializerlib中已经包含了一个替代方案。它是急切的序列化器——它将序列化引用,就好像它们是嵌入的文档一样。它可以这样使用:

/**
 * @ODM\ReferenceMany(targetDocument="MyTargetDocument")
 * @Sds\Serializer(@Sds\ReferenceSerializer('Sds\DoctrineExtensions\Serializer\Reference\Eager'))
 */
protected $myDocumentProperty;

或者提供了一个替代的速记注释:

/**
 * @ODM\ReferenceMany(targetDocument="MyTargetDocument")
 * @Sds\Serializer(@Sds\Eager))
 */
protected $myDocumentProperty;

替代ReferenceSerializers必须实施Sds\DoctrineExtensions\Serializer\Reference\ReferenceSerializerInterface

另外,我清理了忽略注释,因此可以将以下注释添加到属性中,以便对序列化进行更细粒度的控制:

@Sds\Serializer(@Sds\Ignore('ignore_when_serializing'))
@Sds\Serializer(@Sds\Ignore('ignore_when_unserializing'))
@Sds\Serializer(@Sds\Ignore('ignore_always'))
@Sds\Serializer(@Sds\Ignore('ignore_never'))

例如,设置@Sds\Serializer(@Sds\Ignore('ignore_when_serializing'))email 属性 - 这意味着可以将电子邮件发送到服务器进行更新,但永远不能将其序列化到客户端以确保安全。

最后,如果您没有注意到,sds 注释支持继承和覆盖,因此它们可以很好地处理复杂的文档结构。

于 2012-12-06T08:26:24.077 回答
-1

将 Doctrine ODM 文档转换为数组或 JSON 的另一种非常简单、独立于框架的方法 - http://ajaxray.com/blog/converting-doctrine-mongodb-document-tojson-or-toarray

该解决方案为您提供了一个为您的 ODM 文档提供toArray()和功能的特征。toJSON()use您的 Document 中设置特征后,您可以执行以下操作 -

<?php
// Assuming in a Symfony2 Controller
// If you're not, then make your DocmentManager as you want
$dm = $this->get('doctrine_mongodb')->getManager();
$report = $dm->getRepository('YourCoreBundle:Report')->find($id);

// Will return simple PHP array
$docArray = $report->toArray();

// Will return JSON string
$docJSON = $report->toJSON();

顺便说一句,它只适用于 PHP 5.4 及更高版本。

于 2014-05-13T04:42:31.107 回答