我有一个Listener类其中当张贴或线程实体被建立,在类别表更新这些字段:
last_post_thread_title
last_post_thread_slug
last_poster_username
last_post_body
last_post_created_at
is_last_post_op
和last_post_created_at
在线程表中。
class LastPostListener
{
public function postPersist(LifeCycleEventArgs $args)
{
$entity = $args->getObject();
$entityManager = $args->getObjectManager();
$this->handleEvent($entityManager, $entity);
}
public function postUpdate(LifeCycleEventArgs $args)
{
$entity = $args->getObject();
$entityManager = $args->getObjectManager();
$this->handleEvent($entityManager, $entity);
}
public function handleEvent($entityManager, $entity)
{
if (!$entity instanceof Post && !$entity instanceof Thread) {
return;
}
$isPost = $entity instanceof Post;
$thread = $isPost ? $entity->getThread() : $entity;
$post = $isPost ? $entity : $thread;
$category = $thread->getCategory();
$category->setLastPostThreadTitle($thread->getTitle());
$category->setLastPostThreadSlug($thread->getSlug());
$category->setLastPostBody($post->getBody());
$category->setLastPosterUsername($post->getUser()->getUsername());
$category->setLastPostCreatedAt($post->getCreatedAt());
$category->setIsLastPostOp(!$isPost);
$thread->setLastPostCreatedAt($entity->getCreatedAt());
$entityManager->persist($thread, $category);
$entityManager->flush();
}
}
但是,当编辑现有线程或后置实体时,之前提到的类别表字段不会更新。
这是一个与prePersist()和更新前的()事件,有或没有冲洗相同。
当然,可以将所有$category->set
行直接添加到Controller update
函数中,但这很脏。
此处应使用哪个事件,或者还有其他解决方案?谢谢
答案 0 :(得分:1)
在Doctrine documentation中解释了这种行为的原因,并详细说明了每种事件类型中允许的操作。如果您看一下这篇文章,您会发现preUpdate
事件的限制非常严格,而postUpdate
甚至都不相关。一般来说,当前问题的主要原因是在flush()
已经运行时尝试调用flush()
。
如果您想同步信息-有几种方法:
onFlush
事件监听器。此事件使您可以访问计划提交的所有计算出的更改,并且可以检查这些更改以确定要更新的内容。但是,这可能并不容易,因为您将需要处理UnitOfWork
方法,这些方法公开计算的更改的内部表示形式,例如getScheduledEntityUpdates()
和其他类似方法。如果您要在此事件中的实体中进行某些更改,则还需要手动重新计算更改集。 您可以实现单独的类,该类将提供自己的flush()
方法,该方法基本上需要如下所示:
class CustomFlush {
/**
* @var EntityManager
*/
private $em;
/**
* @var array
*/
private $changes = [];
public function flush($entity = null) {
// Perform normal flushing operation
$this->em->flush($entity);
// If there was some changes collected - apply them
if (!empty($this->changes)) {
$categories = [];
// Apply changes from $this->changes to Category entities,
// collect them in $categories and flush separately
if (!empty($categories)) {
$this->em->flush($categories);
}
}
}
public function preUpdate(LifeCycleEventArgs $args) {
// Collect updates from Post and Thread and store it into $this->changes
}
}