Serialization 使用MongoDB ODM实现文档序列化
我试图通过读取文档的元数据来处理文档的序列化。我的灵感来自于使用条令ORM的实体,并对其进行了修改,以匹配条令ODM处理文档的方式。不幸的是,有些东西不能正常工作,因为一个文档从未被序列化多次,即使它被第二次引用,也会导致不完整的序列化 例如,它为属于某个位置1(请参阅)的user1(请参阅)输出此(json)。然后,它输出我们应该再次看到user1的位置和属于它的用户,但我们没有:Serialization 使用MongoDB ODM实现文档序列化,serialization,zend-framework2,doctrine-odm,doctrine-mongodb,Serialization,Zend Framework2,Doctrine Odm,Doctrine Mongodb,我试图通过读取文档的元数据来处理文档的序列化。我的灵感来自于使用条令ORM的实体,并对其进行了修改,以匹配条令ODM处理文档的方式。不幸的是,有些东西不能正常工作,因为一个文档从未被序列化多次,即使它被第二次引用,也会导致不完整的序列化 例如,它为属于某个位置1(请参阅)的user1(请参阅)输出此(json)。然后,它输出我们应该再次看到user1的位置和属于它的用户,但我们没有: { id: "505cac0d6803fa1e15000004", login: "user1",
{
id: "505cac0d6803fa1e15000004",
login: "user1",
places: [
{
id: "505cac0d6803fa1e15000005",
code: "place1",
users: [
{
id: "505c862c6803fa6812000000",
login: "user2"
}
]
}
]
}
我想这可能与阻止循环引用有关,但有办法解决吗
另外,我正在ZF2应用程序中使用它,是否有更好的方法使用ZF2序列化程序实现它
谢谢你的帮助。我已经为DoctrineODM编写了一个序列化程序。您可以在-look-in
lib/Sds/DoctrineExtensions/Serializer
中找到它
如果您使用的是zf2,那么您可能还喜欢它,它配置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
这一切仍在进行中,因此任何意见/改进都将不胜感激。当您遇到这些LIB的问题时,只需将它们登录到github,它们就会得到及时的解决
最后,关于序列化嵌入文档和引用文档的注意事项—嵌入文档应与其父文档一起序列化,而引用文档不应序列化。这反映了数据保存在数据库中的方式。这也意味着循环引用不是问题
更新
我已经将更新推送到Sds/DoctrineExtensions/Serializer,以便它现在可以正确处理引用。更新了以下三(五)种方法:
toArray/toJson
fromArray/fromJson
applySerializeMetadataToArray
前两个是自解释的-最后一个是允许应用序列化规则,而不必将db结果添加到文档中
默认情况下,引用将序列化为如下数组:
[$ref: 'CollectionName/DocumentId']
/**
* @ODM\ReferenceMany(targetDocument="MyTargetDocument")
* @Sds\Serializer(@Sds\ReferenceSerializer('MyAlternativeSerializer'))
*/
protected $myDocumentProperty;
/**
* @ODM\ReferenceMany(targetDocument="MyTargetDocument")
* @Sds\Serializer(@Sds\ReferenceSerializer('Sds\DoctrineExtensions\Serializer\Reference\Eager'))
*/
protected $myDocumentProperty;
$ref
引用风格是Mongo内部使用的,因此它看起来很合适。给出的引用格式期望它可以用作RESTAPI的URL
通过定义一个替代的ReferenceSerializer
可以覆盖默认行为,如下所示:
[$ref: 'CollectionName/DocumentId']
/**
* @ODM\ReferenceMany(targetDocument="MyTargetDocument")
* @Sds\Serializer(@Sds\ReferenceSerializer('MyAlternativeSerializer'))
*/
protected $myDocumentProperty;
/**
* @ODM\ReferenceMany(targetDocument="MyTargetDocument")
* @Sds\Serializer(@Sds\ReferenceSerializer('Sds\DoctrineExtensions\Serializer\Reference\Eager'))
*/
protected $myDocumentProperty;
库中已经包含了一个备用的ReferenceSerializer
。它是热切的序列化程序-它将序列化引用,就像它们是嵌入的文档一样。它可以这样使用:
[$ref: 'CollectionName/DocumentId']
/**
* @ODM\ReferenceMany(targetDocument="MyTargetDocument")
* @Sds\Serializer(@Sds\ReferenceSerializer('MyAlternativeSerializer'))
*/
protected $myDocumentProperty;
/**
* @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;
备用referenceserializer
必须实现Sds\DoctrineExtensions\Serializer\Reference\ReferenceSerializerInterface
此外,我还清理了ignore注释,因此可以将以下注释添加到属性中,以便对序列化进行更细粒度的控制:
@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_serialization'))
放在电子邮件属性上-这意味着电子邮件可以发送到服务器进行更新,但为了安全起见,永远不能序列化到客户端
最后,如果您没有注意到的话,sds注释支持继承和重写,因此它们可以很好地处理复杂的文档结构。将Doctrine ODM文档转换为数组或JSON的另一种非常简单、独立于框架的方法- 此解决方案提供了一个特性,为ODM文档提供了
toArray()
和toJSON()
函数。使用
在文档中标记特征后,您可以执行以下操作-
<?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();
Hi@superdweebie,谢谢你的帮助。我尝试了您的序列化程序,但遇到了一个问题,即引用的文档仍然作为对象进行序列化和检索,因为似乎没有检查$mapping['reference']
以不添加它们。另外,对于不返回字符串(如日期对象)的getter呢?另一方面,如果您不在序列化程序本身中检索文档,您将如何公开某种API来访问您的应用程序中引用文档的数据?嘿@jhuet,感谢您花时间试一试。我将为serializer ref文档添加一个测试用例(我想我没有)。至于API,我正在考虑使用如下内容:。我实际上还没有必要这样做,这就是为什么代码不是100%。但是这是一个很好的改变,可以使lib更加坚固一些。没问题:)dojox.json.ref看起来是一个有趣的方法,你知道它被广泛采用了吗?到目前为止,在我访问的任何API上,引用的文档都只是作为普通文档输出。顺便说一句,它似乎并不能解决如何检索这些引用的文档。在服务器端,如果文档是第一次发送,您如何知道它是作为参考还是作为普通文档?我怀疑客户是否应该在每次请求时发送他所知道的所有文档?@jhuet我刚刚推动了一些更改,如上所述。他们可能会有所帮助。为了回答我的问题,@superdweebie制作了一个伟大的教义库,他在下面描述了它,其中包含一个序列化程序。如果您使用即时抓取,那么您将返回所有文档。现在,虽然您可能会遇到循环引用问题,但我们正在努力实现一个最大嵌套深度选项。@laalto,我已经添加了使用此解决方案的代码示例。谢谢