我目前有一个实体,我想在加载时对其稍加修改。此修改将是一次更改,然后将与实体一起保留在新字段中。
为了阐明我当前的目标:实体是一个“位置”,并构成嵌套集的一部分。它具有名称,lft/rgt值和ID。我对该实体执行的一项计算量大的任务是获取完整的位置路径并将其显示为文本。例如,对于位置实体“Waterloo”,我要显示为“Waterloo |伦敦|英国”。这涉及遍历整个集合(到根节点)。
为了减少此操作的开销,我在Location实体上创建了一个新字段,可以使用该值进行标记(并在位置(或树中的任何位置)名称被修改时更新)。考虑到我的应用程序处于实时状态,我需要避免将其作为一个一次性进程运行,因为这会在数据库上造成相当大的一次性命中,相反,我想在每个位置(不包含每个位置)时应用此更新。该值)被加载。但是,我认为Doctrine的postLoad事件机制对于实现此目标将是完美的。
Location实体不是由我的应用程序直接加载的,它们将始终是关系的反面。考虑到这一点,以及该学说的postLoad事件的事实:
我没有办法轻轻地进行这些修改。
有人对此有任何建议或经验吗?
最佳答案
通过使用实体管理器上的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);
}
}