2013-07-26 2 views
1

У меня есть скрипт import, который считывает XML-файл и добавляет данные в базу данных MySQL. XML-файл содержит Match-Data и связанные с ним события.Doctrine - Удаление и немедленное добавление сущностей в ArrayCollection

У меня есть следующие субъекты

  • MatchList (не лучшее название, но другая тема)
  • MatchEvent

Соответствующие отношения к моему вопросу:

Внутри MatchList (обратная сторона)

/** 
* @OneToMany(targetEntity="MatchEvent", mappedBy="match", orphanRemoval=true) 
*/ 
private $events; 

public function __construct($uId) 
{ 
    $this->setId($uId); 
    $this->events = new ArrayCollection(); 
} 

Внутри MatchEvent (владеющая сторона)

/** 
* @ManyToOne(targetEntity="MatchList", inversedBy="events") 
* @JoinColumn(name="match_id", referencedColumnName="id") 
*/ 
private $match; 

Внутри импорт-скрипт У меня есть цикл для каждого матча. Внутри цикла я хочу удалить все события, которые в настоящее время назначены этому совпадению. И сразу после того, как я хочу добавить новые события из xml-файла в это совпадение.

События должны быть полностью удалены из базы данных. Не только ссылка на матч.

Упрощенный пример

XML-Content

Match1 
    EventA 
    EventC 
    EventF 

перед импортом

Match1 
    EventA 
    EventB 

После импорта должно быть, как это

Match1 
    EventA 
    EventC 
    EventF 

Так событие может быть

  • delete + add (EventA).
  • удалить (событие В)
  • добавить (EventF)

Это происходит потому, что XML содержит обновления и исправления для события. Поэтому единственный надежный способ - удалить все назначенные события и добавить текущие действительные события из последнего xml.

Моя проблема заключается в удалении части В сочетании с немедленным добавлением. Каждая задача для нее работает.

Я пробовал разные методы (также читал документацию доктрины), но я не могу заставить его работать.

После соответствующей части сценария с некоторыми вариантами, которые я попробовал (закомментировать) (не весь код. Посмотрите на «...» Я надеюсь, что этого достаточно, чтобы понять мою проблему/ошибку)

try 
{ 
    foreach($matches as $matchNode) 
    { 
     $match = new \MatchList($matchNode['uID']); 
     ... 
     $previousEvents = $match->getEvents(); 
     foreach($previousEvents as $previousEvent) 
     { 
      $match->removeEvent($previousEvent); 
      //$previousEvent->setMatch(null); 
      //$this->em->remove($previousEvent); 
      //$this->em->persist($previousEvent); 
     } 

     foreach($teamData->Goal as $goal) 
     { 
      ... 
      $event = new \MatchEvent($match); 
      $event->setPlayer($player); 
      $event->setType($goal['Type']); 
      $event->setPeriod($goal['Period']); 

      $this->em->persist($event); 
      $match->addEvent($event); 
     } 
     ... 
     $this->em->persist($match); 
    } 
    $this->em->flush(); 
} 
catch(Exception $e){} 

Независимо от того, что я пробовал, он никогда не работал должным образом.Иногда я получаю сообщение об ошибке (пропущенный каскад сохраняется) или не возникает ошибка, но также и удаление. Только когда я выполняю одну задачу сразу (удалять или добавлять), она работает.

Я знаю, что изменения, внесенные только в обратную сторону, не сохраняются в доктрине, поэтому я попытался вызвать remove в объектах MatchEvent. Или попытался отключить весь массив ArrayCollection и с помощью orphanRemoval также удалить объекты.

Я застрял в попытке. Надеюсь, кто-то может помочь мне понять, что я делаю неправильно, и что будет правильным.

Спасибо

Редактировать

Может быть, это полезно, чтобы добавить все изменения, я пытался.

Вариант 1)

Без добавлять объекты сразу после: Удалить события из БД (ХОРОШО)

С добавлять объекты сразу после: ERROR: Новый объект был найден через отношения «MatchList # событий ', который не был настроен на каскадное сохранение операций для объекта: MatchEvent @ XYZ. (БАД)

$previousEvents = $match->getEvents(); 
foreach($previousEvents as $previousEvent) 
{ 
    $this->em->remove($previousEvent); 
} 

Вариант 2)

Без добавлять объекты сразу после: Удалить события из БД (ХОРОШО)

С добавлять объекты сразу после: ERROR: Новый объект был найден через отношения «MatchList # events», которые не были сконфигурированы для каскадной операции persist для объекта: MatchEvent @ XYZ. (БАД)

$previousEvents = $match->getEvents(); 
foreach($previousEvents as $previousEvent) 
{ 
    $previousEvent->setMatch(null); 
    $this->em->remove($previousEvent); 
    $this->em->detach($previousEvent); 
} 

Вариант 3)

Без добавлять объекты сразу после: Ошибка: Новый объект был найден через отношения «MatchList # событий», которые не были настроены на каскаде сохраняются операции для лица : MatchEvent @ XYZ. (BAD)

С добавлением объектов сразу после: Не пробовали, потому что даже удаление не сработало.

$previousEvents = $match->getEvents(); 
foreach($previousEvents as $previousEvent) 
{ 
    $previousEvent->setMatch(null); 
    $this->em->detach($previousEvent); 
} 

Это должно работать, или я missunderstood это: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/faq.html#i-call-clear-on-a-one-to-many-collection-but-the-entities-are-not-deleted

Вариант 4)

Без добавлять объекты сразу после: удвоился данные в БД, потому что ни одно событие не был удален, и все события, дополнительные вставить с match_id NULL. (BAD)

С добавлением объектов сразу после: Не пробовали, потому что даже удаление не сработало.

$previousEvents = $match->getEvents(); 
foreach($previousEvents as $previousEvent) 
{ 
    $previousEvent->setMatch(null); 
    $this->em->detach($previousEvent); 
    $this->em->persist($previousEvent); 
} 

ответ

2

Я нашел решение.

Для этого решения важно добавить «orphanRemoval = true».

/** 
* @OneToMany(targetEntity="MatchEvent", mappedBy="match", orphanRemoval=true) 
*/ 
private $events; 

В цикле я удаляю каждую сущность из ArrayCollection с помощью removeElement. Поскольку orphanRemoval истинно, объект также удаляется.

foreach($match->getEvents() as $event) 
{ 
    $match->getEvents()->removeElement($event); 
} 

Добавление объектов такое же, как показано выше.

Я надеюсь, что объяснение поможет другим с той же проблемой.

Смежные вопросы