6

私はこのシナリオを持っています:

  • オブジェクト A は他のオブジェクト B、C、D への参照を持っています
  • オブジェクト B は、他のオブジェクト A、F、G への参照を持っています。
  • オブジェクト C は、他のオブジェクト A への参照を持っています...

等々。

私のコードでは、tmp の理由からオブジェクト (A など) の「コピー」を作成する必要があります (いいえ、別の構造を使用することはできません。オブジェクトのコピーが必要です)。

を使用するcloneと、明らかに、オブジェクトのクローンが作成されますが、オブジェクトに関連するオブジェクトはクローンされません。Aオブジェクトの観点から、オブジェクト自体のクローンとしてB、C、Dに割り当てるために
マジックメソッドをオーバーライドできることを完全に知っていますが、非常に多くのオブジェクトがあります(それらの多くはDoctrineに含まれています)各オブジェクトのクローン機能のオーバーライドは避けたいと思います。__clone()ArrayCollection

別の方法として、教義からオブジェクトを再取得して新しいオブジェクトを作成できると考えました。

$aCopy = $this->entity_manager
                       ->getRepository('MyBundle:A')
                       ->find($a->getId());

$aのインスタンスはどこですかclass A

この操作を行った後-もちろん、それは「間違っています」。なぜなら、doctrineがそのオブジェクトを「すでにフェッチ済み」としてマークし、そのpointer( )*を返すと思われるからです-関数を使用して2つのオブジェクトのIDを単純に出力spl_object_hash()し、もちろん再び、それらは同じオブジェクト ID を参照するため、同じオブジェクトを参照します。

PS .:

この操作の後に元のオブジェクトを使用できるようにする必要があるため、 doctrinedetach()関数を使用できません

質問

どうすればこの状況に対処できますか? ご覧のとおり、私は 2 つの異なる方法を試しましたが、どれも私を満足させるものではありませんでした。

ノート

私はphpにもタグを付けました.php-pureベースの別のソリューションを誰かが教えてくれたら、それも考慮に入れるからです。

(*)

この場合、記事はエンティティ マネージャーから 2 回アクセスされますが、その間に変更されます。Doctrine 2 はこれを実現し、ID 1234 のアーティクルの 1 つのインスタンスへのアクセスのみを提供します。EntityManager からそれを取得する頻度や、使用している Query メソッドの種類 (find、Repository Finder、またはDQL)。これは「アイデンティティ マップ」パターンと呼ばれ、Doctrine が PHP リクエストごとに取得された各エンティティと ID のマップを保持し、同じインスタンスを返し続けることを意味します。

それは私が前に言ったことを確認します

4

2 に答える 2

3

答えは思ったほど複雑ではありませんでした。

$this->entity_manager->clear();このエンティティ マップをクリアし、データベースから新しいオブジェクトに強制的にリロードするのに十分な呼び出しのようです!

$this->entity_manager->clear();
$aCopy = $this->entity_manager
                       ->getRepository('MyBundle:A')
                       ->find($a->getId());
            $this->logger->debug('Original Obj: '.spl_object_hash($a));
            $this->logger->debug('Copied Obj:      '.spl_object_hash($aCopy));

これは印刷されます

[2013-02-08 12:07:20] app.DEBUG: 元のオブジェクト: 000000006523 645c 000000004b1160d1 [] [] [2013-02-08 12:07:20] app.DEBUG: コピーされたオブジェクト: 000000006523 66e3 00010 []

于 2013-02-08T11:14:48.120 に答える
1

私が知る限り、これはすぐにサポートされる D2 の動作ではないため、クローン操作を自分で実装する必要があると思います。

そうは言っても、D2エンティティをシリアライズしてからアンシリアライズするとどうなるか100%確信が持てませんが、これはあなたが望むことをするかもしれません(かなり不快な方法ではありますが)。さらに、エンティティ最初にフェッチした後、すぐに受け取ったものを切り離し、「ライブ」コピーへの参照が元のインスタンス化ポイントの外に伝播する前に結果を再度フェッチすることができます (クエリが結果キャッシュを使用している場合)。これはあまりペナルティを負うべきではありません)。ただし、一時的にコピーを操作しているだけなので、おそらくこれは大きな問題にはなりません。

エンティティ マネージャーをクリアする WRT は、すべての管理対象エンティティを切り離すため、望ましくない副作用が生じる可能性があります。

HTH。

于 2013-02-08T11:17:05.163 に答える