如何使用Doctrine的事件监听器更改相关实体

3
使用Symfony和Doctrine,我有一个用户实体和一个
地址
实体。每个用户可以拥有0个或多个地址,其中一个是他的默认地址。
因此,当我将默认地址从一个更改为另一个时,我应该将那个设置为默认地址,其他地址设置为非默认(一个布尔字段)。
我尝试使用事件监听器来实现这一点,因此当
地址
实体被更新时,我启动了后续更新事件,将所有其他地址设置为非默认,类似于下面的内容:
class AddresssListener
{
    public function postUpdate(LifecycleEventArgs $event)
    {
        $entity = $event->getEntity();
        if ($entity instanceof Address) {
            $this->changeDefaultAddress($entity, $event);
        }
    }

    private function changeDefaultAddress($address, $event)
    {
        if ($address->getIsDefault() == true) {
            foreach ($address->getUser()->getBillingDatas() as $another_address) {
                if ($address != $another_address) {
                    $another_address->setIsDefault(false);
                    $em = $event->getEntityManager();
                    $em->persist($another_address);
                }
            }
        }
    }
}

代码执行正确,没有显示错误,但是对非默认地址的更改没有保存。

你知道你没有持久化更新的对象吗?你更新了$another_address并持久化了$another_billing_data。 - jahller
嗨,抱歉,是我的错。我已经在问题中更正了代码。是的,我持久化了另一个地址。 - petekaner
而 flush() 方法在哪里?另外,为什么你要在 foreach 循环中每次实例化 em? - Srdjan
我也尝试了使用flush,但它也没有起作用。我应该将em实例化移出循环。 - petekaner
你发布的代码仍未显示$another_address的刷新。Doctrine事件很棘手。我强烈建议在用户对象中添加changeDefaultAddress并将逻辑移动到其中。 - Cerad
您可以尝试调用recomputeSingleEntityChangeSet(),如此文章所述:http://vvv.tobiassjosten.net/symfony/update-associated-entities-in-doctrine/ - Carlos Granados
1个回答

1
如果一个用户只能有一个默认地址,那么您还应该确保数据库模型仅支持一个地址作为默认地址。我建议将当前默认地址的“Address”设置为“User”的关系(在与地址的一对多关系之外,添加另一个“Address”($defaultAddress)和“User”之间的一对一关联)。然后,您可以简单地这样做:
$user->setDefaultAddress($address);
$em->persist($user);
$em->flush();

这可以通过一次数据库操作完成,而不是您示例中的两次操作(PostPersist在第一次操作提交后被调用)。
现在很容易获取当前默认地址:
$address = $user->getDefaultAddress();

这很有道理,会使默认地址在数据模式中可见。谢谢! - petekaner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接