我已经阅读了有关生命周期事件的文档,以及有关在生命周期事件期间更改或保留新实体的几个问题。打电话给EnitityManager::flush()
似乎是一个问题。
好的,但是仔细查看文档,有一个代码示例,其中字段在postPersist中更改,但没有调用刷新。
我检查了一下,建议的更改没有写入数据库。只有持久化的对象才会收到更改。
<?php
/** @Entity @HasLifecycleCallbacks */
class User
{
// ...
/**
* @Column(type="string", length=255)
*/
public $value;
/** @PostPersist */
public function doStuffOnPostPersist()
{
$this->value = 'changed from postPersist callback!';
}
}
也许应该将其添加到文档中。起初我被误导了。
但是,当添加 LifecyleEventArgs 参数并刷新包含的 EntityManager 时,它们将写入数据库:
/** @PostPersist */
public function doStuffOnPostPersist(LifecycleEventArgs $args)
{
$this->value = 'changed from postPersist callback!';
$args->getEntityManager()->flush(); // works in my tests. Is this safe to use ?
}
我不知道如何解释文档是否可以在postPersist中调用flush
。
如您所见,我正在寻找一种可靠的方法,在插入或更新实体后对实体执行某种后处理。我必须使用 postPersist,因为我需要自动生成的主键值。
附带问题:如果是,可以刷新,那么我是否也可以将其他对象保留在 PostUpdate 中?这样:
/** @PostPersist */
public function doStuffOnPostPersist(LifecycleEventArgs $args)
{
$this->value = 'changed from postPersist callback!';
$obj = new OtherObject("value " . $this->value);
$args->getEntityManager()->persist($obj);
$args->getEntityManager()->flush(); // works in my tests. Is this safe to use ?
}
侧面问题:我已经尝试了最后一个变体,它似乎有效。但它是否有效,或者我可能会创建深度递归堆栈?根据文档,postPersist代码是在刷新期间调用的,因此如果我在postPersist期间调用flush,我必须注意不要保留执行相同处理程序的对象,这将导致无限递归。这是对的吗?
我检查过,建议的更改没有写入数据库。只有持久化的对象才会收到更改。
也许应该将其添加到文档中。起初我被误导了。
文档中的代码不会尝试保留对 value 属性的此修改 在数据库中,这就是不调用flush()
的原因。它只是显示一个示例,此值也可能是未映射到类User
的数据库属性。
我不知道如何解释文档是否可以在postPersist中调用刷新。
可以在 PostPersist 生命周期回调中调用flush()
以更改映射的属性 您的实体。在 PostPersist 回调中,您的实体已插入到数据库中。通过更改属性 值和调用flush()
您的实体将被标记为要更新,因此 PostPersist 事件不会 再次调度(将调度更新前/更新后事件(。
附带问题:如果是,可以刷新,那么我是否也可以将其他对象保留在 PostUpdate 中?
在PostPersist 事件回调中持久化另一个实体类的新对象也没有问题, 但是如果你尝试在这个PostPersist回调中持久化相同(用户(类的对象,你将有一个 无限递归,你很容易理解。
侧面问题:我已经尝试了最后一个变体,它似乎有效。但它是否有效,或者我可能会创建深度递归堆栈?
正如我之前所解释的,如果不持久化回调所属的同一类 (User( 的对象,这段代码不会创建太深的递归堆栈或无限循环。flush()
将恰好被调用两次。尽管在还必须处理关联时,事情可能会变得更加复杂,但在您的示例中没有这样的问题。