вступление
Итак, у меня есть объект Presence, за которым следит Doctrine.
У меня также есть другой объект Decision, за которым Doctrine не следит.
Объект Presence имеет атрибут $decisions, тип ArrayCollection и содержит от 0 до n объектов Decision.
Поскольку я не храню каждый объект Decision, содержащийся в ArrayCollection, я ввел атрибут $decision как массив Doctrine, и пока все работает.
Я могу получить весь объект Presence из базы данных, и он содержит все объекты Decision, которые я добавил к нему.
Проблема
Когда я редактирую один объект Decision, который присутствует в коллекции ArrayCollection моего объекта Presence, например:
foreach($Presence->getDecisions() as $decision) {
$decision->setMorning($value);
}
Модификации применяются локально, и я могу видеть их, когда делаю dump($Presence);
Presence {#2354 ▼
#id: 8
#decisions: ArrayCollection {#1409 ▼
-elements: array:6 [▼
0 => Decision {#1408 ▼
#token_id: "005867b2915438c03383bb831d87c26346c586d6ecd46b735c7a23b4fabb682a8ac34a90ea3d53cc55c2209deaa83337abeb2b98ded43967fcfb0f4d04d5ada6"
#date: DateTime @1531692000 {#1407 ▶}
#morning: -1
#afternoon: 0
}
1 => Decision {#1406 ▶}
2 => Decision {#1404 ▶}
3 => Decision {#1402 ▶}
4 => Decision {#1400 ▶}
5 => Decision {#1398 ▶}
]
}
#last_edit_date: DateTime @1532109183 {#2454 ▼
date: 2018-07-20 19:53:03.062940 Europe/Berlin (+02:00)
}
#user: User {#1393 ▶}
}
На этом dump()
видно, что атрибут #morning: -1
является результатом вызова сеттера.
Но когда я пытаюсь сбросить изменения с помощью $this->entityManager->flush();
, коллекция ArrayCollection не была изменена.
Сначала я подумал, что это проблема обнаружения изменений, поэтому я добавил поле #last_edit_date
DateTime в свой объект Presence.
Самое интересное, что этот атрибут прекрасно обновляется при очистке.
Кажется, что ArrayCollection по какой-то причине не будет обновляться.
ОБНОВИТЬ
Чтобы завершить мой пост, вот дополнительная информация:
Полный метод в контроллере
/**
* @Route(name="edit_decision", path="/edit-decision/{tokenDate}/{dayPart}/{newValue}")
*/
public function EditDecisionAction(Request $request)
{
$token = $request->get('tokenDate');
$dayPart = $request->get('dayPart');
$newValue = intval($request->get('newValue'));
$myPresence = $this->em->getRepository('AppBundle:Presence')->findOneBy([
'user' => $this->connectedUser
]);
/** @var ArrayCollection $decisionCollection */
$decisionCollection = $myPresence->getDecisions();
$found = FALSE;
/** @var Decision $decision */
foreach ($decisionCollection as $decision) {
if ($decision->getTokenId() == $token) {
$found = TRUE;
if ($dayPart === 'morning') {
$decision->setMorning($newValue);
}elseif ($dayPart === 'afternoon') {
$decision->setAfternoon($newValue);
}
break;
}
}
if (!$found) {
throw $this->createNotFoundException();
}
// I set a new Date to trigger a modification on the Presence Entity : It works
$myPresence->setLastEditDate(new \DateTime());
// Here is the dump that you can see above
dump($myPresence);
$this->em->flush();
try{
$this->em->flush();
return $this->json([
'status' => TRUE
]);
}catch (\Exception $exception) {
return $this->json([
'status' => FALSE
]);
}
}
Атрибут, содержащий ArrayCollection :
/**
* Doctrine Type Array
*
* @ORM\Column(type="array", nullable=true)
*/
protected $decisions;
Любая помощь или даже подсказки приветствуются! Спасибо :)
ОБНОВЛЕНИЕ 2
Возможно, я нашел решение благодаря этому сообщению:
Как заставить Doctrine обновлять поля типа массива?
Проблема возникает из-за типа массива доктрины, под которым я храню свои объекты:
Doctrine использует идентичный оператор (===) для сравнения изменений между старыми и новыми значениями. Оператор, используемый для одного и того же объекта (или массива объектов) с разными данными, всегда возвращает значение true. Есть и другой способ решить эту проблему, вы можете клонировать объект, который нужно изменить.
Обновление 3
Nope по-прежнему не сохраняет изменения, внесенные в элементы ArrayCollection в базе данных. Собираюсь попробовать Клонирование: Добавление: Удаление старого, и мы увидим, что произойдет.
FormType
, который вы используете в своем контроллере. - person Preciel   schedule 20.07.2018