学说"反向"孤儿清除

时间:2013-02-15 16:18:57

标签: doctrine-orm

我有两个实体(简化):

class EncryptedMasterKey {
    /**
     * @ORM\ManyToOne(targetEntity="ExchangeFile", inversedBy="encryptedMasterKeys")
     * @ORM\JoinColumn(name="exchange_file_id", referencedColumnName="id")
     *
     * @var ExchangeFile
     */
    protected $exchangeFile;
}

class ExchangeFile {
    /**
     * @ORM\OneToMany(targetEntity="EncryptedMasterKey", mappedBy="exchangeFile", orphanRemoval=true, cascade={"persist", "remove"})
     */
    protected $encryptedMasterKeys;
}

数据库中一个EncryptedMasterKey可能有很多ExchangeFile个。如果删除ExchangeFile,则会删除所有相关的加密MasterKeysorphanRemoval=truecascade={"persist", "remove"}以确保是这种情况)。到目前为止,非常好。

现在,当实际文件在硬盘上加密时,必须有至少一个EncryptedMasterKey ,以便可以解密文件。因此,当EncryptedMasterKey被删除并且我发现它是ExchangeFile的最后一个时,我还必须删除ExchangeFile ,因为它无法再被解密。如果没有至少一个ExchangeFileEncryptedMasterKey就无法生存。

我如何实现这一目标? @ORM\PreRemove课程中的EncryptedMasterKey对我没有帮助,因为我无法访问实体管理器:

class EncryptedMasterKey {
    //...
    /** @ORM\PreRemove */
    public function removeOrphanExchangeFile()
    {
        if ($this->exchangeFile->isTheOnlyMasterKey($this))
            // I don't have access to the Entity Manager,
            // so how do I delete the ExchangeFile?
    }
}

这有什么优雅的解决方案吗?

感谢您的时间。

1 个答案:

答案 0 :(得分:4)

您可以使用event subscriber并创建如下的类:

class MyEncryptedMasterSubscriber implements \Doctrine\Common\EventSubscriber
{
    public function getSubscribedEvents()
    {
        return array(\Doctrine\ORM\Events::onFlush);
    }

    public function onFlush(\Doctrine\ORM\Events\OnFlushEventArgs $eventArgs)
    {
        $uow = $eventArgs->getEntityManager()->getUnitOfWork();


        foreach ($uow->getScheduledEntityDeletions() AS $entity) {
            if (
                $entity instanceof EncryptedMasterKey 
                && $entity->getExchangeFile()->isTheOnlyMasterKey($entity)
            ) {
                $uow->scheduleForDelete($entity->getExchangeFile());
            }
        }
    }
}

您可以在the documentation上了解有关如何在Symfony 2的特定情况下注册订阅者的更多信息。