У меня есть скрипт 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);
}