Doktrin bruger Identitetskort mønster til at spore objekter. Så hver gang du henter et objekt fra databasen, gemmer Doctrine en reference til dette objekt i dets UnitOfWork. Og grundlæggende bruger den ID'et som en nøgle til at administrere objekter inde i UnitOfWork.
F.eks.
$objectA = $this->entityManager->find('EntityName', 1);
$objectB = $this->entityManager->find('EntityName', 1);
ville kun udløse én SELECT-forespørgsel mod databasen. I det andet opkald vil doktrinen tjekke identitetskortet og ville finde det samme ID uden at lave en database rundtur. Selvom du bruger proxy-objekt, vil objektet have samme ID.
Men for
$objectA = $repository->findOneBy(array('name' => 'Benjamin'));
$objectB = $repository->findOneBy(array('name' => 'Benjamin'));
du vil se to forespørgsler i din SQL-log, på trods af at du refererer til det samme objekt. Doktrin kender kun objekter efter ID , så en forespørgsel efter et andet kriterium skal gå til databasen, selvom den blev udført før.
Men doktrinen er smart, den skaber ikke en ny enhed, men får ID'et og ser efter, om den allerede er i hukommelsen.
PHP følger copy-on-write-paradigmet, det er et optimeringsprincip. En reel kopi af en variabel laves kun, når variablen er ændret. Så hukommelsesforbruget til en anmodning, der læser objekter fra databasen, er det samme, som hvis man ikke skulle beholde en variabel kopi.
Så kun når du ændrer variabler, opretter dine applikationer nye variable internt og bruger hukommelse.
Så når du kalder flush , doktrin itererer over Identiy Map og sammenligner hver obecjts oprindelige egenskab med de aktuelle værdier. Hvis der registreres ændringer, vil den stå i kø for en OPDATERING-forespørgsel. Kun faktisk opdaterede felter ændres i databasen.
Sådan optimerer du
Så nogle gange giver det mening at markere objekter som skrivebeskyttet (kun indsæt og fjern), så de ikke vil være i ændringssættet (du kan gøre det i din xml-mapping-fil eller med anmærkninger eller i din php-kode).
$entityManager->getUnitOfWork()->markReadOnly($entity)
Eller tøm kun én enhed
$entityManager->flush($entity)