2015-12-17 4 views
0

Я некоторое время боролся с раздражающей проблемой. Я пытаюсь создать объекты уведомлений, связанные с InventoryItems, которые истекают.Doctrine EventListener onFlush не сохраняет исходную сущность

Эти объекты InventoryItems создаются автоматически для пользователей, но пользователи могут редактировать их и устанавливать для них дату истечения срока их действия отдельно. При сохранении, если у InventoryItem есть дата истечения срока действия, создается и ассоциируется с ним объект уведомления. Таким образом, эти объекты уведомлений создаются, когда объект обновляется, и поэтому событие onPersist не будет работать.

Все, кажется, работает нормально и Уведомления генерируются при сохранении InventoryItems, как ожидалось. Единственная проблема заключается в том, что когда уведомление создается впервые, даже если оно сохранено правильно, изменения в InventoryItem не сохраняются. Это уведомление с правильной датой истечения срока действия создается, но дата истечения срока действия не сохраняется в InventoryItem.

Вот мой onFlush код:

public function onFlush(OnFlushEventArgs $args) 
{ 
    $em = $args->getEntityManager(); 
    $uow = $em->getUnitOfWork(); 
    foreach ($uow->getScheduledEntityUpdates() as $entity) { 
     if ($entity instanceof NotificableInterface) { 
      if ($entity->generatesNotification()){ 
       $notification = $this->notificationManager->generateNotificationForEntity($entity) ; 
       if ($notification) { 
        $uow->persist($notification) ; 
       } 
       $entity->setNotification($notification) ; 
       $uow->persist($entity); 
       $uow->computeChangeSets(); 
      } 
     } 
    } 
} 

Проблема возникает только в первый раз, когда уведомление, связанный с объектом, то есть в первый раз дата истечения срока действия устанавливается на InventoryItem. В более поздних случаях, когда дата истечения срока действия обновляется, обновление правильно отражается как на Notification, так и на InventoryItem.

Любые идеи или предложения будут оценены.

Благодаря

ответ

4

Вам нужно позвонить computeChangeset специально на вновь созданный или обновленный лица. Просто вызвать computeChangeSets недостаточно.

$metaData = $em->getClassMetadata('Your\NameSpace\Entity\YourNotificationEntity'); 
    $uow->computeChangeSet($metaData, $notification); 
2

Thanks Richard. Ты указал мне в правильном направлении. Мне нужно было пересчитать набор изменений на родительском объекте (InventoryItem), чтобы заставить работу работать исправно. Кроме того, я должен был назвать computeChangeSets на единице работы, чтобы избавиться от недопустимого номера параметра (например, один объяснил symfony2 + doctrine: modify a child entity on `onFlush`: "Invalid parameter number: number of bound variables does not match number of tokens")

Примечание Я кончался также извлекая:

if ($notification) { 
    $uow->persist($notification) ; 
} 

Который никогда не имел смысла , так как я установил каскад в ассоциации в моей сущности и должен был автоматически каскадироваться.

Мое окончательное решение:

public function onFlush(OnFlushEventArgs $args) 
{ 
    $em = $args->getEntityManager(); 
    $uow = $em->getUnitOfWork(); 

    foreach ($uow->getScheduledEntityUpdates() as $entity) { 
     if ($entity instanceof NotificableInterface) { 
      if ($entity->generatesNotification()){ 
       $notification = $this->notificationManager->generateNotificationForEntity($entity) ; 
       $entity->setNotification($notification) ; 
       // if ($notification) { 
       // $uow->persist($notification) ; 
       // } 
       $metaData = $em->getClassMetadata(get_class($entity)); 
       $uow->recomputeSingleEntityChangeSet($metaData, $entity); 
       $uow->computeChangeSets(); 
      } 
     } 
    } 
} 
Смежные вопросы