我有2个实体,Invoice和Advance。进展与发票有关,与ManyToOne有关。在添加,编辑和推进时,我希望相应地编辑发票总额。我为Advances postPersist设置了一个听众,如下所示:
class PostPersistListener
{
protected $container;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
public function postPersist(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
$em = $args->getEntityManager();
// Advance Listener
if ($entity instanceof Advance) {
// Modification du total de la facture mère
$invoice = $entity->getInvoice();
echo '<pre>';
\Doctrine\Common\Util\Debug::dump($invoice);
echo '</pre>';
$newTotal = $invoice->getTotalMaster() - $entity->getTotalMaster();
$invoice->setTotalMaster($newTotal);
echo '<pre>';
\Doctrine\Common\Util\Debug::dump($invoice);
echo '</pre>';
$em->flush();
}
}
}
事件被很好地触发了。第一个dump()显示如下:
object(stdClass)#1379 (49) {
["__CLASS__"]=>
string(32) "Evo\BackendBundle\Entity\Invoice"
["id"]=>
int(1)
["totalMaster"]=>
float(250)
}
第二次转储():
object(stdClass)#1379 (49) {
["__CLASS__"]=>
string(32) "Evo\BackendBundle\Entity\Invoice"
["id"]=>
int(1)
["totalMaster"]=>
float(240)
}
所以&#34; totalMaster&#34;财产被修改。但$ em-&gt; flush()似乎并没有更新数据库中的字段。我错过了什么吗?
答案 0 :(得分:3)
首先,正如其名称所暗示的那样,PostPersist仅在初始持续操作之后触发,即仅针对新对象。编辑现有对象不会触发事件。
来自:http://docs.doctrine-project.org/en/latest/reference/events.html#lifecycle-events
postPersist - The postPersist event occurs for an entity after the entity has been made persistent.
It will be invoked after the database **insert** operations.
Generated primary key values are available in the postPersist event.
对这些事件的处理也有严格的限制。基本上,刷新操作已经在进行中,因此更新实体的任何事情都充其量是有问题的。具体做法是:
来自:http://docs.doctrine-project.org/en/latest/reference/events.html#postupdate-postremove-postpersist
The three post events are called inside EntityManager#flush().
Changes in here are not relevant to the persistence in the database,
but you can use these events to alter non-persistable items, like non-mapped fields, logging or
even associated classes that are directly mapped by Doctrine.
你几乎不可能使用prePersist和preUpdate来解决这个问题,但这些问题有其自身的问题。
@kix有正确的方法。更新发票总额是域功能,应使用域事件处理。
P.S。您不需要对通过Doctrine检索的现有对象调用persist。
答案 1 :(得分:0)
您错过了$em->persist($invoice)
行。
另外,我建议使用Symfony的内置事件来实现这个逻辑,而不是prePersist
个侦听器。这背后的简单原因是您的代码处理业务逻辑而不是持久性逻辑。您应该使用AdvanceModified
服务(它应该可供您的控制器使用)发送event_dispatcher
事件,然后在监听器中处理它。