Создание / сохранение нового документа во время события preUpdate в doctrine-mongodb
Я использую doctrine-mongodb-odm-1.0.0-BETA10
и пытается обеспечить некоторую пользовательскую логику на основе \InitialDocument
в то время как preUpdate
событие работает.
Допустим \InitialDocument
получил некоторое состояние, которое должно вести себя как начальное для нового \StateDocument
, Я делаю что-то вроде этого:
class InitDocListener implements \Doctrine\Common\EventSubscriber {
public function getSubscribedEvents()
{
return [
Events::preUpdate
];
}
public function preUpdate($args){
$document = $args->getDocument();
if($document instanceOf InitialDocument && $document->getState() == 'mine'){
$stateDocument = new \StateDocument();
$stateDocument->setInitDocument($document);
$args->getDocumentManager()->persist($stateDocument);
//no flush cause recursion happens
}
}
}
prePersist
событие от \StateDocument
случается, но он не сохранит новый документ в БД. а также postPersist
Событие соответственно никогда не будет запущено.
Есть еще немного пользовательской логики, но все в области событий. В какой-то момент эта логика может вызвать исключение, которое должно остановить событие обновления InitialDocument
так InitialDocument
состояние зависит от \StateDocument
процесс создания в сфере бизнеса.
Как я могу решить эту проблему? preFlush
событие для запуска до пересчета changeSet не определить InitialDocument
пример. Так что это какой-то трюк для "поиска" обновлений на preFlush
и заставить меня думать, что это не правильный путь. Пожалуйста, посоветуйте мне правильно. Благодарю.
1 ответ
Я создал тестовый пример для вашего варианта использования здесь. Одна вещь, которая выделялась из кода в вашем вопросе, заключалась в том, что вы не звонили recomputeSingleDocumentChangeSet()
в документе, который вы изменяли во время обратного вызова жизненного цикла, как указано в preUpdate
документация Но даже с этим вызовом новый документ не будет вставлен. Это связано с тем, что UnitOfWork выполняет обновления после вставок и загрузок. Полный заказ можно увидеть в UnitOfWork's commit()
метод:
- Документ upserts
- Вставки документов
- Обновление документа
- Дополнительные обновления (запланированные внутри постоянных классов)
- Удаление коллекций
- Обновления коллекции
- Удаление документов
Когда preUpdate
событие отправлено, upserts/inserts для новых документов уже произошло. Даже с призывом recomputeSingleDocumentChangeSet()
Вы заканчиваете тем, что планировали документ для вставки, но UnitOfWork игнорирует это и в конечном итоге отменяет его при очистке всех очередей расписания здесь.
В то время как ODM может легко проверить наличие дополнительных вставок после обработки обновлений, в некоторых ситуациях это может привести к бесконечному циклу. Заказ UnitOfWork предшествовал моей работе над проектом, но я рискую зацикливаться, возможно, была проблема, когда была задумана первоначальная реализация.
В качестве обходного пути вы можете захотеть, чтобы слушатель выгрузил новые документы для вставки в какой-то другой контейнер (или сам слушатель), а затем проверил после факта наличие дополнительных документов для сохранения / очистки.