协会的学说后加载事件


Doctrine postLoad event for associations

>我目前有一个实体,我想在加载时稍微修改一下。此修改将是一次性更改,然后将与实体一起保留在新字段中。

为了澄清我目前的目标:实体是一个"位置",并构成嵌套集的一部分。它有一个名称,lft/rgt值和一个Id。我使用此实体执行的一项计算成本高昂的任务是获取完整的位置路径并将其显示为文本。例如,对于位置实体"滑铁卢",我想显示为"滑铁卢|伦敦|联合王国"。这涉及遍历整个集(到根节点)。

为了降低成本,我在 Location 实体上创建了一个新字段,可以使用此值标记该字段(并在修改位置(或树中的任何位置)名称时更新)。考虑到我的应用程序处于实时状态,我需要避免将其作为一次性进程运行,因为它会对数据库造成相当严重的一次性打击,相反,我想在每个位置(没有该值)加载时应用此更新。但是,我认为Doctrine的后加载事件机制非常适合实现这一目标。

位置实体不是由我的应用程序直接加载的,它们将始终是关系的反侧。有了这个头脑,以及学说的后加载事件的事实:

  • 不加载(允许访问)任何关联的数据
  • 仅因拥有实体而被解雇

我没有办法轻轻地进行这些修改。

有人对此有任何建议或经验吗?

我能够在 postLoad 事件中使用实体管理器上的 initializeObject() 方法加载关联的 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);
    }
}