我有一个实体与A两个多对多关系BC
class A
{
/**
* @ORM\ManyToMany(targetEntity=B::class, inversedBy="as")
*/
private ?Collection $bs = null;
/**
* @ORM\ManyToMany(targetEntity=C::class, inversedBy="as")
*/
private ?Collection $cs = null;
}
C和B之间还有一个OneToMany:
class C
{
/**
* @ORM\OneToMany(targetEntity=B::class, mappedBy="c")
*/
private Collection $bs;
}
我正在 A 上监听 prePersist / preUpdate(尽管我也尝试过 onFlush / postPersist 和 postUpdate):
App\Event\ADoctrineListener:
tags:
- { name: doctrine.event_listener, event: prePersist, lazy: true }
- { name: doctrine.event_listener, event: preUpdate, lazy: true }
这个想法是寻找 A 的 Cs 的变化,以便 A 的 Bs 总是从 C 的 Bs 派生:
class ADoctrineListener
{
public function prePersist(LifecycleEventArgs $args): void
{
$this->maybeUpdateBs($args);
}
public function preUpdate(LifecycleEventArgs $args): void
{
$this->maybeUpdateBs($args);
}
private function maybeUpdateBs(LifecycleEventArgs $args): void
{
$a = $this->getA($args);
if (null === $a) {
return;
}
if (false === $this->didCsChange($a)) {
return;
}
$this->removeBsOfRemovedCs($a);
$this->addBsOfAddedCs($a);
}
private function didCsChange(A $a): bool
{
return $a
->getCs()
->isDirty()
;
}
private function removeBsOfRemovedCs(A $a): void
{
$removedCs = $a
->getCs()
->getDeleteDiff()
;
foreach ($removedCs as $c) {
foreach ($c->getBs() as $b) {
$a->removeB($b);
}
}
}
private function addBsOfAddedCs(A $a): void
{
$insertedCs = $a
->getCs()
->getInsertDiff()
;
foreach ($insertedCs as $c) {
foreach ($c->getBs() as $b) {
$a->addB($b);
}
}
}
private function getA(LifecycleEventArgs $args): ?A
{
if (false === $args->getObject() instanceof A) {
return null;
}
return $args->getObject();
}
}
逻辑本身运行良好,我可以看到对象处于我想要保存的状态。
然而,问题是,我不能让它持续到数据库中。
我已经尝试了通过简单地重新保留 A 所能想到的任何事情:
$args->getEntityManager()->persist($a)
...重新计算变更集:
$em = $args->getEntityManager();
$uow = $em->getUnitOfWork();
$meta = $em->getClassMetadata(get_class($a));
$uow->recomputeSingleEntityChangeSet($meta, $a);
以及它们的组合,但是虽然我没有收到错误,但新关联的 B 不会出现在数据库中。
所以我想要找出的是如何正确地让教义知道我对主题的相关集合进行了更改并让它保持不变。