Doctrine utilizza la Mappa dell'identità modello per tracciare gli oggetti. Quindi, ogni volta che si recupera un oggetto dal database, Doctrine conserva un riferimento a questo oggetto all'interno del suo UnitOfWork. E fondamentalmente usa l'ID come chiave per gestire gli oggetti all'interno del suo UnitOfWork.
Es.
$objectA = $this->entityManager->find('EntityName', 1);
$objectB = $this->entityManager->find('EntityName', 1);
lancerebbe solo una query SELECT sul database. Nella seconda chiamata la dottrina controllerà la mappa dell'identità e troverebbe lo stesso ID senza fare un roundtrip del database. Anche se utilizzi un oggetto proxy, l'oggetto avrà lo stesso ID.
Ma per
$objectA = $repository->findOneBy(array('name' => 'Benjamin'));
$objectB = $repository->findOneBy(array('name' => 'Benjamin'));
vedresti due query nel tuo registro SQL, nonostante tu faccia riferimento allo stesso oggetto. Dottrine conosce gli oggetti solo per ID , quindi una query per un criterio diverso deve andare al database, anche se è stata eseguita in precedenza.
Ma la dottrina è intelligente, non crea una nuova entità ma ottiene l'ID e cerca se è già in memoria.
PHP segue il paradigma copy-on-write, è un principio di ottimizzazione. Una copia reale di una variabile viene eseguita solo quando la variabile viene modificata. Quindi l'utilizzo della memoria per una richiesta che legge oggetti dal database è lo stesso che se non si conservasse una copia variabile.
Quindi, solo quando modifichi le variabili, le tue applicazioni creano nuove variabili internamente e consumano memoria.
Quindi, quando chiami colore , la dottrina esegue un'iterazione sulla mappa dell'identità e confronta la proprietà originale di ciascun oggetto con i valori correnti. Se vengono rilevate modifiche, si accoderà per una query UPDATE. Solo i campi effettivamente aggiornati vengono modificati nel database.
Come ottimizzare
Quindi a volte ha senso contrassegnare gli oggetti come di sola lettura (solo inserimento e rimozione), quindi non saranno nel changeset (puoi farlo nel tuo file di mappatura xml o con annotazioni o nel tuo codice php).
$entityManager->getUnitOfWork()->markReadOnly($entity)
Oppure svuota solo un'entità
$entityManager->flush($entity)