Intro
So, i have an entity Presence that is watched by Doctrine.
I also have another entity Decision that is not watched by Doctrine.
The Presence entity has an attribute $decisions, typed ArrayCollection and contains 0 to n Decision entities.
Since i don't store each Decision object that is contained within the ArrayCollection, i typed the attribute $decision as Doctrine Array and everything is working so far.
I can get the whole Presence object back from database & it contains every Decision objects that i added to it.
The problem
When i edit one Decision object that is present in the ArrayCollection of my Presence object like :
foreach($Presence->getDecisions() as $decision) {
$decision->setMorning($value);
}
The modifications are applied locally, and i can see them when doind a 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 ▶}
}
On this dump()
you can see that the attribute #morning: -1
is the result of the setter call.
But when i try to flush the changes with $this->entityManager->flush();
the ArrayCollection has not been modified.
At first i thought it was a problem of changes detection, so i added a #last_edit_date
DateTime field onto my Presence entity.
The fun part is that this attribute is updating just fine when flushing.
It seems that the ArrayCollection won't update for some reason.
UPDATE
To complete my post here is additional informations :
The full method in the controller
/**
* @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
]);
}
}
The attribute that contains the ArrayCollection :
/**
* Doctrine Type Array
*
* @ORM\Column(type="array", nullable=true)
*/
protected $decisions;
Any help or even hints are welcome ! Thanks :)
UPDATE 2
I may have found the solution thanks to this post :
How to force Doctrine to update array type fields?
The problem comes from the doctrine Array type under which i store my objects :
Doctrine uses identical operator (===) to compare changes between old and new values. The operator used on the same object (or array of objects) with different data always return true. There is the other way to solve this issue, you can clone an object that needs to be changed.
Update 3
Nope still doesn't persists the changes made on the ArrayCollection's items in the database. Gonna try Cloning : Adding : Removing the old one and we will se what happens.