2

我試圖通過讀取文檔的元數據來處理文檔的序列化。我從this implementation獲得靈感來源於具有Doctrine ORM的實體,並對其進行修改以匹配Doctrine ODM處理文檔的方式。不幸的是,某些文檔無法正常工作,因爲即使第二次引用了一個文檔也不會多次序列化,從而導致序列化不完整。使用Doctrine MongoDB進行文檔序列化ODM

例如,它輸出屬於某個place1的用戶1(參見User document)(參見Place document)的此(在json中)。然後,它輸出的地方,屬於它的地方,我們應該再次看到user1的用戶,但我們不這樣做:

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

我想這可能與一些防止循環引用,但有沒有辦法解決它?

此外,我在ZF2應用程序中使用它,會有更好的方法來實現這個使用ZF2串行器?

感謝您的幫助。

+0

爲了回答我的問題,@superdweebie製作了一個偉大的教義庫,他在下面描述了包含一個序列化器。如果您使用預先抓取,那麼您將返回所有文檔。目前,儘管您可能會遇到循環引用問題,但我們正在研究[一個特性](https://github.com/superdweebie/doctrineExtensions/issues/6)來實現最大嵌套深度選項。 – jhuet

回答

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 /串行器,以便它現在可以正確處理引用。下面的三個(5個)的方法已被更新:

toArray/toJson 
fromArray/fromJson 
applySerializeMetadataToArray 

前兩個是自explainitory - 最後就是讓不必滋潤分貝成果轉化爲文檔應用序列化規則。

默認情況下,引用將被序列化到一個數組是這樣的:

[$ref: 'CollectionName/DocumentId'] 

$ref風格引用的是什麼蒙戈在內部使用,因此它似乎是適當的。給出了參考的格式,期望它可以用作REST API的URL。

默認行爲可以通過defineing替代ReferenceSerializer這樣來覆蓋:

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

一個替代ReferenceSerializer已經包含與所述庫。這是一個熱切的序列化器 - 它將序列化引用,就像它們是嵌入式文檔一樣。它可以像這樣使用:

/** 
* @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'))放在電子郵件屬性上 - 這意味着可以將電子郵件發送到服務器進行更新,但不能將其序列化到客戶端以確保安全。

最後,如果您沒有注意到,sds註釋支持繼承和覆蓋,所以它們可以很好地處理複雜的文檔結構。

+0

嗨@superdweebie,謝謝你在這裏的幫助。我試過你的序列化程序,但遇到了引用文檔仍然序列化並作爲對象檢索的問題,因爲[here](https://github.com/superdweebie/doctrineExtensions/blob/master/lib/Sds/DoctrineExtensions/Serializer/Serializer。 php#L190)似乎沒有檢查'$ mapping ['reference']'不添加它們。另外,getter不返回日期對象等字符串呢? – jhuet

+0

在附註中,如果您沒有在序列化程序本身中檢索這些文件,您將如何公開某種API以訪問您的應用程序的數據並引用文檔? – jhuet

+0

嘿@jhuet,感謝您抽出寶貴時間。我將爲序列化引用文檔添加一個測試用例(我不認爲我有過)。至於API,我想用這樣的東西:http:// dojotoolkit。組織/參考導/ 1.8/DojoX中/ JSON/ref.html。我還沒有真的需要這樣做(還沒有),這就是爲什麼代碼不全是100%。但這是一個很好的改變,以增強更多一點。 – superdweebie

-1

另一個很簡單,架構獨立的方式轉化學說ODM文檔數組或JSON - http://ajaxray.com/blog/converting-doctrine-mongodb-document-tojson-or-toarray

該解決方案爲您提供了一個特點,提供toArray()toJSON()功能,爲您的ODM文件。 use荷蘭國際集團在您的文檔的特點後,你可以做 -

<?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(); 

BTW,這將在PHP 5.4及以上的只有工作。

+0

@laalto,我已經添加了使用此解決方案的代碼示例。謝謝。 – Anis

相關問題