Я хочу отслеживать изменения в поле доктрины. Я использую Symfony 2.5.0 и Doctrine 2.2.3.
Пока у меня есть EventSubscriber
который подписывается на preUpdate
, Здесь я хочу создать новый объект, который хранит новое и старое значение и содержит ссылку на объект, который обновляется.
Проблема в том, что я не могу найти способ сохранить эту новую сущность. Если я persist()
в preUpdate
а также flush()
в postUpdate
, это работает, если я изменяю только одну сущность. Если несколько сущностей изменены, я получаю сообщение об ошибке, что набор изменений пуст.
Я пытался играть с разными событиями с разными результатами. Пустые страницы, объекты отслеживания не сохраняются и т. Д.
Я думаю, что это должно быть распространено, но я не могу найти примеры.
Не используйте preUpdate или postUpdate, у вас будут проблемы. Взгляни на onFlush вместо.
На данный момент у вас есть доступ к полному набору изменений, чтобы вы могли узнать, какие поля были изменены, что было добавлено и т. Д. Вы также можете безопасно сохранять новые объекты. Обратите внимание как документы скажем, вам придется пересчитать наборы изменений, когда вы сохраните или измените объекты.
Простой пример, который я собрал вместе, не проверял, но что-то похожее на это даст вам то, что вы хотите.
public function onFlush(OnFlushEventArgs $args) {
$entityManager = $args->getEntityManager();
$unitOfWork = $entityManager->getUnitOfWork();
$updatedEntities = $unitOfWork->getScheduledEntityUpdates();
foreach ($updatedEntities as $updatedEntity) {
if ($updatedEntity instanceof YourEntity) {
$changeset = $unitOfWork->getEntityChangeSet($updatedEntity);
if (!is_array($changeset)) {
return null;
}
if (array_key_exists('someFieldInYourEntity', $changeset)) {
$changes = $changeset['someFieldInYourEntity'];
$previousValueForField = array_key_exists(0, $changes) ? $changes[0] : null;
$newValueForField = array_key_exists(1, $changes) ? $changes[1] : null;
if ($previousValueForField != $newValueForField) {
$yourChangeTrackingEntity = new YourChangeTrackingEntity();
$yourChangeTrackingEntity->setSomeFieldChanged($previousValueForField);
$yourChangeTrackingEntity->setSomeFieldChangedTo($newValueForField);
$entityManager->persist($yourChangeTrackingEntity);
$metaData = $entityManager->getClassMetadata('YourNameSpace\YourBundle\Entity\YourChangeTrackingEntity');
$unitOfWork->computeChangeSet($metaData, $yourChangeTrackingEntity);
}
}
}
}
}
Вы можете быть заинтересованы в EntityAudit bundle.
Это позволяет настроить, какие объекты должны отслеживаться. Затем он вводит понятие изменения базы данных. Каждая ревизия имеет временную метку, имя пользователя и список затронутых объектов.
Затем вы можете найти все ревизии, которые влияют на конкретную сущность:
$revisions = $auditReader->findRevisions('AppBundle\Entity\Article', 1);
или создать его в конкретной ревизии:
$oldArticle = $auditReader->find(
'AppBundle\Entity\Article',
$id = 1,
$rev = 2
);
так что вы можете легко сравнить текущее и старое состояние объекта.
Пакет также поставляется с примерами представления, демонстрирующими, как отображать список ревизий, сравнивать объекты в разных версиях и многое другое.