Я работаю над проектом на базе Symfony 2.8, который в основном представляет собой онлайновую адресную книгу.
EntityDeletionListener
используется для обработки postRemove
событий, чтобы добавить некоторую информацию в журнал удалений, которая необходима для некоторого внутреннего учета:
class EntityDeletionListener implements EventSubscriber {
public function getSubscribedEvents() {
return array('postRemove');
}
public function postRemove(LifecycleEventArgs $args) {
$entity = $args->getEntity();
if (!$entity->shouldAddToDeleteLog())
return ;
$em = $args->getEntityManager();
$repo = $em->getRepository('AppBundle:DeleteLog');
$log = $repo->createEntity();
$log->setGuid($entity->getGuid());
...
$em->persist($log);
// Flush entity manager if not disabled in entity settings
if ($entity->shouldFlushDeleteLog())
$em->flush();
}
}
Это работает без проблем: каждый раз, когда объект Contact
удаляется, запись в журнале удаления создается автоматически.
Сейчас я работаю над возможностью массового удаления любого количества выбранных Contacts
.
Для ускорения процесса менеджер сущностей сбрасывается не после каждой операции удаления, а только после обработки некоторого пакета.
class ContactRepository extends EntityRepository {
public function bulkDelete($guids) {
$this->_em->getConnection()->beginTransaction();
try {
$batchSize = 100;
$currentBatch = 0;
foreach ($guids as $guid) {
$contact = $this->findOneByGuid($guid);
if ($contact) {
// DO NOT FLUSH EVERY DELETE LOG
$contact->setDeleteLogFlush(false);
$this->_em->remove($contact);
$currentBatch++;
if ($currentBatch % $batchSize === 0)
$this->_em->flush();
}
}
$this->_em->flush();
$this->_em->getConnection()->commit();
} catch (\Exception $ex) {
$this->_em->getConnection()->rollBack();
return false;
}
}
}
Задача 1:
Если я использую $contact->setDeleteLogFlush(false)
, чтобы избежать автоматической очистки каждого DeleteLog автоматически, DeleteLogs
не сохраняется вообще. Также сущности Contact
удаляются корректно, и postRemove
выполняется для каждой операции удаления, журналы не сохраняются в БД.
Нет исключений или других ошибок, которые объясняли бы, почему журналы не сохраняются. Даже если будет ошибка, в этом случае полная транзакция не будет выполнена, и Contacts
также не будет удален. Но они удалены ...
Задача 2:
Если НЕ использовать $contact->setDeleteLogFlush(false)
, прослушиватель postRemove
сбрасывает каждую новую DeleteLog
, я получаю следующее исключение, как только несколько записей удаляются одновременно:
Uncaught PHP Exception Symfony\Component\Debug\Exception\FatalThrowableError: "Type error: Argument 2 passed to Doctrine\DBAL\Connection::delete() must be of the type array, null given
Как это решить? Почему журналы, созданные в приемнике postRemove
, не сохраняются при очистке менеджера сущностей?