Doctrine 事件:如何跟踪 ManyToMany 集合的添加/删除?

问题描述 投票:0回答:3

我有一个

Application
实体,它与
SortList
实体具有多对多关系。拥有方是
Application
。有一个简单的联接表可以创建此关系的映射。

以下是

Application
实体在管理集合方面的外观:

/**
 * Add sortLists
 *
 * @param \AppBundle\Entity\SortList $sortList
 * @return Application
 */
public function addSortList(SortList $sortList)
{
    $this->sortLists[] = $sortList;
    $sortList->addApplication($this);

    return $this;
}

/**
 * Remove sortLists
 *
 * @param \AppBundle\Entity\SortList $sortList
 */
public function removeSortList(SortList $sortList)
{
    $this->sortLists->removeElement($sortList);
    $sortList->removeApplication($this);
}

/**
 * Get sortLists
 *
 * @return \Doctrine\Common\Collections\Collection
 */
public function getSortLists()
{
    return $this->sortLists;
}

我想跟踪何时从

SortLists
 添加或删除 
Application

我已经了解到我无法使用

postUpdate
生命周期事件来跟踪这些更改集合。

相反,我似乎应该使用 onFlush,然后使用

$unitOfWork->getScheduledCollectionUpdates()
$unitOfWork->getScheduledCollectionDeletions()

对于更新,我发现我可以使用“内部”方法

getInsertDiff
来查看集合中添加了哪些项目,并
getDeleteDiff
来查看集合中哪些项目被删除。

但我有一些担忧:

  1. 如果集合中的所有项目都被删除,则无法查看哪些项目实际被删除,因为
    $unitOfWork->getScheduledCollectionDeletions()
    没有此信息。
  2. 我正在使用标记为“内部”的方法;似乎它们可能会在我不知情的情况下“消失”或在未来的某个时刻被重构?
symfony doctrine-orm
3个回答
0
投票

我在https://stackoverflow.com/a/75277337/5418514

中解决了这个空的getDeleteDiff

有时这是空的原因是一个古老但仍然存在的问题。目前的解决办法就是自己重新取数据。

public function onFlush(OnFlushEventArgs $args)
{
    $uow = $args->getEntityManager()->getUnitOfWork();
    
    foreach ($uow->getScheduledCollectionDeletions() as $collection) {
        /**
         * "getDeleteDiff" is not reliable, collection->clear on PersistentCollection also clears the original snapshot
         * A reliable way to get removed items is: clone collection, fetch original data
         */
        $removedData = $collection->getDeleteDiff();
        if (!$removedData) {
            $clone = clone $collection;
            $clone->setOwner($collection->getOwner(), $collection->getMapping());
            // This gets the real data from the database into the clone
            $uow->loadCollection($clone);

            // The actual removed items!
            $removedData = $clone->toArray();
        }
    }
}

0
投票

我尝试了上述方法,但没有成功,但我发现更简单的方法是将它们一一删除,例如

foreach ($collection->toArray() as $item) {
  $collection->removeElement($item);
}

这允许我在从集合中删除项目时记录更改。但来到这里实际上帮助我了解我的问题是什么(使用 $collection->clear() )


-1
投票

我认为下面的示例涵盖了您需要的所有内容,因此您只需在应用程序中实现您想要/需要的内容即可。

该网站中还有许多其他有用的侦听器示例,因此只需使用 listener

 关键字的搜索功能即可。有一次我对 M-N 关联做了同样的事情,但找不到例子。如果可以的话我会发布它,但不确定是否可以!

© www.soinside.com 2019 - 2024. All rights reserved.