Я прочитал документы о событиях жизненного цикла и несколько вопросов по SO об изменении или сохранении новых сущностей во время событий жизненного цикла. Вызов 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 ?
}
Я не знаю, как сообщить интерпретировать документы, можно ли вызывать flush внутри postPersist.
Как видите, я ищу надежный способ выполнить некоторую постобработку моих объектов после их вставки или обновления. Мне нужно использовать 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 называется в течение flush, поэтому, если я вызываю flush во время postPersist, я должен быть осторожен, чтобы не сохранить объект, который выполняет тот же обработчик, что приведет к бесконечной рекурсии. Это верно?




I checked that, and the suggested change is not written to the DB. Only the object being persisted does receive the change.
Maybe one should add this to the docs. I was mislead at first.
Код в документации не пытается сохранить эту модификацию свойства value.
в базе данных поэтому не вызывается flush(). Это просто пример, и это значение также может быть не сопоставлено со свойством базы данных класса User.
I don't know how to interpret the docs about whether it is OK or not to call flush inside the postPersist.
Можно вызвать flush() для обратного вызова жизненного цикла PostPersist, чтобы изменить сопоставленное свойство.
вашего объекта. В обратном вызове PostPersist ваша сущность уже была вставлена в вашу базу данных. Изменяя свойство
значение и вызывая flush(), ваша сущность будет помечена как подлежащая обновлению, поэтому событие PostPersist не будет
будут отправлены снова (вместо этого будут отправляться события Pre / PostUpdate).
Side question: If yes, it is ok to flush, could I then also persist other objects in PostUpdate?
Также нормально без проблем сохранить новый объект другого класса сущности в обратном вызове события PostPersist, но если вы попытаетесь сохранить объект того же класса (User) в этом обратном вызове PostPersist, у вас будет бесконечная рекурсия, как вы легко понимаете.
Side-side question: I have tried the last variant, and it seems to work. But is it efficient, or am I possibly creating deep recursion stacks?
Как я объяснял ранее, этот код не создает слишком глубоких рекурсивных стеков или бесконечных циклов, если не сохраняются объекты того же класса (User), которому принадлежит обратный вызов. flush() будет вызываться ровно два раза. Хотя все может усложниться, когда придется иметь дело с ассоциациями, в вашем примере такой проблемы нет.