2013-01-24 28 views
5

我目前有一個實體,我想稍微修改後加載。此修改將是一次性更改,然後將與實體一起保留在新的字段中。學會postLoad事件協會

澄清我目前的目標:實體是一個「位置」並構成嵌套集的一部分。它有一個名稱,lft/rgt值和一個Id。我用這個實體執行的一個計算成本很高的任務是獲取完整的位置路徑並將其顯示爲文本。例如,對於位置實體「滑鐵盧」,我想顯示爲「滑鐵盧|倫敦|英國」。這涉及遍歷整個集合(到根節點)。

爲了降低成本,我在Location實體上創建了一個新的字段,可以使用此值進行標記(並且在位置(或樹中的任何位置)名稱被修改時更新爲/。考慮到我的應用程序處於活動狀態,我需要避免將其作爲一次性過程運行,因爲它會在數據庫上產生相當大的一次性衝擊,相反,我想在每個位置應用此更新(無該值)被加載。我認爲Doctrine的postLoad事件機制對於實現這一點來說是完美的,但是..

Location實體不是由我的應用程序直接加載的,它們將始終是關係的反面。有了這個想法,而事實上,這種理論的餐後事件:

  • 不加載(允許訪問)任何相關的數據
  • 僅觸發爲擁有實體

我也沒辦法輕輕地做出這些修改。

任何人有任何建議,或經驗呢?

+0

作爲個人建議,我不會在持久層中通過花哨的邏輯來處理這個問題。相反,構建一個聚合模型來代理對實體的調用,並最終處理獲取父項。這將適合您的服務層 – Ocramius

回答

5

我能夠通過在實體管理器上使用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); 
    } 
}