Doctrine utilise la carte d'identité motif pour suivre les objets. Ainsi, chaque fois que vous récupérez un objet de la base de données, Doctrine conserve une référence à cet objet dans son UnitOfWork. Et fondamentalement, il utilise l'ID comme clé pour gérer les objets à l'intérieur de son UnitOfWork.
Par exemple
$objectA = $this->entityManager->find('EntityName', 1);
$objectB = $this->entityManager->find('EntityName', 1);
déclencherait une seule requête SELECT sur la base de données. Dans le deuxième appel, la doctrine vérifiera la carte d'identité et trouvera le même ID sans faire un aller-retour dans la base de données. Même si vous utilisez un objet proxy, l'objet aura le même ID.
Mais pour
$objectA = $repository->findOneBy(array('name' => 'Benjamin'));
$objectB = $repository->findOneBy(array('name' => 'Benjamin'));
vous verriez deux requêtes dans votre journal SQL, malgré le fait que vous référencez le même objet. Doctrine ne connaît les objets que par ID , donc une requête pour un critère différent doit aller dans la base de données, même si elle a été exécutée auparavant.
Mais la doctrine est intelligente, elle ne crée pas une nouvelle entité mais récupère l'ID et regarde si elle est déjà en mémoire.
PHP suit le paradigme de la copie sur écriture, c'est un principe d'optimisation. Une copie réelle d'une variable n'est faite que lorsque la variable est modifiée. Ainsi, l'utilisation de la mémoire pour une requête qui lit les objets de la base de données est la même que si elle ne conservait pas une copie variable.
Ainsi, ce n'est que lorsque vous modifiez des variables que vos applications créent de nouvelles variables en interne et consomment de la mémoire.
Ainsi, lorsque vous appelez flush , la doctrine itère sur la carte d'identité et compare la propriété d'origine de chaque objet avec les valeurs actuelles. Si des modifications sont détectées, il sera mis en file d'attente pour une requête UPDATE. Seuls les champs réellement mis à jour sont modifiés dans la base de données.
Comment optimiser
Il est donc parfois judicieux de marquer les objets en lecture seule (seulement insérer et supprimer), afin qu'ils ne soient pas dans le jeu de modifications (vous pouvez le faire dans votre fichier de mappage xml ou avec des annotations ou dans votre code php).
$entityManager->getUnitOfWork()->markReadOnly($entity)
Ou vider une seule entité
$entityManager->flush($entity)