I am working with Doctrine ORM and I often see recommendations to call toArray() on a collection before iterating over it when removing elements.
I would like to understand whether this is really necessary and why.
Context
I have a Dossier entity with a OneToMany relationship to Echeance:
#[ORM\OneToMany(mappedBy: 'dossier', targetEntity: Echeance::class, orphanRemoval: true)]
private Collection $echeances;
I want to remove all Echeance entities that do not have an active Reglement.
Code without toArray()
foreach ($dossier->getEcheances() as $echeance) {
if (!$this->hasActiveReglement($echeance)) {
$dossier->removeEcheance($echeance);
}
}
I have seen advice saying that this pattern can be unsafe because the collection is modified while it is being iterated.
Alternative version with toArray()
foreach ($dossier->getEcheances()->toArray() as $echeance) {
if (!$this->hasActiveReglement($echeance)) {
$dossier->removeEcheance($echeance);
}
}
Questions :
Is it actually unsafe to remove elements from a Doctrine Collection while iterating over it?
Can elements really be skipped in this situation, or is this just a precaution?
Does this behavior come from PHP foreach itself, or from Doctrine’s PersistentCollection implementation?
Is using toArray() the recommended best practice in this case?
I would like to understand what happens internally in this case.