6

現在、ロード時に少し変更したいエンティティがあります。この変更は1回限りの変更であり、エンティティとともに新しいフィールドに保持されます。

私の現在の目的を明確にするために:エンティティは「場所」であり、ネストされたセットの一部を形成します。名前、lft / rgt値、およびIDがあります。このエンティティで実行していた計算コストの高いタスクの1つは、完全なロケーションパスを取得し、それをテキストとして表示することでした。たとえば、ロケーションエンティティが「Waterloo」の場合、「Waterloo | London|UnitedKingdom」と表示します。これには、セット全体(ルートノードまで)をトラバースすることが含まれます。

このコストを削減するために、Locationエンティティにこの値をスタンプできる新しいフィールドを作成しました(場所(またはツリー内の任意の場所)の名前が変更されたときに更新されます)。アプリケーションがライブ状態にあることを考えると、これを1回限りのプロセスとして実行することは避けてください。これは、DBに非常に集中的な1回限りのヒットが発生するためです。代わりに、この更新を各場所で(その値)がロードされます。ただし、DoctrineのpostLoadイベントメカニズムはこれを実現するのに最適だと思いました。

Locationエンティティは、アプリケーションによって直接ロードされるのではなく、常にリレーションの逆側になります。これは心であり、DoctrineのpostLoadイベントという事実は次のとおりです。

  • 関連するデータをロード(アクセスを許可)しません
  • エンティティを所有するためにのみ解雇されます

これらの変更をやさしく行う方法はありません。

誰かアドバイスや経験がありますか?

4

1 に答える 1

9

エンティティマネージャーでinitializeObject()メソッドを使用して、postLoadイベント内に関連付けられたLocationオブジェクトをロードすることができました。

/**
 * Upon loading the object, if the location text isn't set, set it
 * @param \Doctrine\ORM\Event\LifecycleEventArgs $args
 */
public function postLoad(\Doctrine\ORM\Event\LifecycleEventArgs $args)
{
    $this->em = $args->getEntityManager();
    $entity = $args->getEntity();

    if ($entity instanceof \Entities\Location)
    {
        if (is_null($entity->getPathText()))
        {
            $entity->setPathText("new value");
            $this->em->flush($entity);
        }
    } elseif ($entity instanceof {parent Entity})
    {
        $location = $entity->getLocation();
        // This triggers the postLoad event again, but this time with Location as the parent Entity
        $this->em->initializeObject($location);
    }
}
于 2013-01-24T15:08:11.407 に答える