2

ドキュメントのメタデータを読み取って、ドキュメントのシリアル化を処理するクラスをコーディングしようとしています。Doctrine ORMを使用するエンティティのこの実装に触発され、DoctrineODMがドキュメントを処理する方法に一致するように変更しました。残念ながら、2回目の参照であっても、1つのドキュメントが複数回シリアル化されることはなく、シリアル化が不完全になるため、何かが正しく機能していません。

たとえば、あるplace1( Place documentを参照)に属するuser1( User documentを参照)に対してこれを(jsonで)出力します。次に、user1が再び表示される場所とそれに属するユーザーを出力しますが、出力しません。

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

循環参照を妨げる何かに関連している可能性があると思いますが、それを回避する方法はありますか?

また、これをZF2アプリケーションで使用していますが、ZF2シリアライザーを使用してこれを実装するためのより良い方法はありますか?

ご協力いただきありがとうございます。

4

2 に答える 2

3

DoctrineODM 用に書かれたシリアライザーを既に持っています。http://github.com/superdweebie/DoctrineExtensionsで見つけることができます- を見てくださいlib/Sds/DoctrineExtensions/Serializer

zf2 を使用している場合は、zf2 で使用するために DoctrineExtensions を構成するhttp://github.com/superdweebie/DoctrineExtensionsModuleも気に入るはずです。

モジュールを使用するには、他のモジュールと同様に 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 に更新をプッシュしました。次の 3 つのメソッドが更新されました。

toArray/toJson
fromArray/fromJson
applySerializeMetadataToArray

最初の 2 つは自明です。最後の 2 つは、データベースの結果をドキュメントにハイドレートすることなく、シリアライゼーション ルールを適用できるようにするためのものです。

デフォルトでは、参照は次のように配列にシリアライズされます。

[$ref: 'CollectionName/DocumentId']

参照の$refスタイルは Mongo が内部で使用しているものなので、適切であると思われました。参照の形式は、REST API への URL として使用できることを想定して指定されています。

ReferenceSerializerデフォルトの動作は、次のような代替を定義することでオーバーライドできます。

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

lib には1 つの代替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

また、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_serializing'))、メール プロパティを設定すると、更新のためにメールをサーバーに送信できますが、セキュリティのためにクライアントにシリアル化することはできません。

そして最後に、sds アノテーションは継承とオーバーライドをサポートしているため、複雑なドキュメント構造でうまく機能します。

于 2012-12-06T08:26:24.077 に答える
-1

Doctrine ODM ドキュメントを配列または JSON に変換する、フレームワークに依存しない非常にシンプルなもう 1 つの方法 - http://ajaxray.com/blog/converting-doctrine-mongodb-document-tojson-or-toarray

このソリューションは、ODM ドキュメントを提供toArray()し機能する特性を提供します。toJSON()ドキュメントで特性を ing した後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();

ところで、PHP 5.4 以降でのみ動作します。

于 2014-05-13T04:42:31.107 に答える