AKTUALISIEREN
Diese Antwort enthält falsche Informationen zu Unterschieden zwischen Proxy-Objekten und Teilobjekten. Weitere Informationen finden Sie in der Antwort von @ Kontrollfreak: https://stackoverflow.com/a/17787070/252591
Proxy-Objekte werden immer dann verwendet, wenn Ihre Abfrage nicht alle Daten zurückgibt, die zum Erstellen einer Entität erforderlich sind. Stellen Sie sich folgendes Szenario vor:
@Entity
class User {
@Column protected $id;
@Column protected $username;
@Column protected $firstname;
@Column protected $lastname;
// bunch of setters/getters here
}
DQL query:
SELECT u.id, u.username FROM Entity\User u WHERE u.id = :id
Wie Sie sehen, werden diese Abfragen firstname
und lastname
Eigenschaften nicht zurückgegeben , daher können Sie kein User
Objekt erstellen . Die Erstellung einer unvollständigen Entität kann zu unerwarteten Fehlern führen.
Aus diesem Grund erstellt Doctrine ein UserProxy
Objekt, das das verzögerte Laden unterstützt. Wenn Sie versuchen, auf eine firstname
Eigenschaft zuzugreifen (die nicht geladen ist), wird dieser Wert zuerst aus der Datenbank geladen.
Ich meine, warum sollte ich einen Proxy verwenden?
Sie sollten Ihren Code immer so schreiben, als hätten Sie überhaupt keine Proxy-Objekte verwendet. Sie können als interne Objekte behandelt werden, die von Doctrine verwendet werden.
Warum kann das verzögerte Laden nicht in der Entität selbst implementiert werden?
Technisch könnte es sein, aber werfen Sie einen Blick auf die Klasse eines zufälligen Proxy-Objekts. Es ist voller schmutziger Code, ugh. Es ist schön, einen sauberen Code in Ihren Entitäten zu haben.
Können Sie mir einen Anwendungsfall geben?
Sie zeigen eine Liste der letzten 25 Artikel an und möchten Details des ersten Artikels anzeigen. Jeder von ihnen enthält eine große Textmenge, sodass das Abrufen all dieser Daten eine Verschwendung von Speicher wäre. Deshalb rufen Sie keine unnötigen Daten ab.
SELECT a.title, a.createdAt
FROM Entity\Article a
ORDER BY a.createdAt DESC
LIMIT 25
$isFirst = true;
foreach ($articles as $article) {
echo $article->getTitle();
echo $article->getCreatedAt();
if ($isFirst) {
echo $article->getContent(); // Article::content is not loaded so it is transparently loaded
// for this single article.
$isFirst = false;
}
}
Proxies
Ein Doctrine-Proxy ist nur ein Wrapper, der eine Entitätsklasse erweitert, um Lazy Loading dafür bereitzustellen.
Wenn Sie den Entitätsmanager nach einer Entität fragen, die einer anderen Entität zugeordnet ist, wird die zugeordnete Entität standardmäßig nicht aus der Datenbank geladen, sondern in ein Proxy-Objekt eingeschlossen. Wenn Ihre Anwendung dann eine Eigenschaft anfordert oder eine Methode dieser Proxy-Entität aufruft, lädt Doctrine die Entität aus der Datenbank (außer wenn Sie die ID anfordern, die dem Proxy immer bekannt ist).
Dies geschieht für Ihre Anwendung vollständig transparent, da der Proxy Ihre Entitätsklasse erweitert.
Doctrine hydratisiert Assoziationen standardmäßig als Lazy-Load-Proxys, wenn Sie sie nicht
JOIN
in Ihrer Abfrage verwenden oder den Abrufmodus auf setzenEAGER
.Jetzt muss ich das hinzufügen, weil ich nicht genug Ruf habe, um überall zu kommentieren:
Leider enthält Crozins Antwort Fehlinformationen.
Wenn Sie eine DQL-Abfrage wie ausführen
Sie erhalten kein (Proxy-) Entitätsobjekt, sondern ein assoziatives Array. Es ist also nicht möglich, zusätzliche Eigenschaften zu laden.
Vor diesem Hintergrund kommt man zu dem Schluss, dass das Anwendungsfallbeispiel auch nicht funktioniert. Die DQL müsste in so etwas geändert werden, um
$article
als Objekt zugreifen zu können:Und die von zurückgegebene Eigenschaft
getContent()
müsste eine Zuordnung sein, um die Inhaltseigenschaften aller 25 Entitäten nicht zu laden .Teilobjekte
Wenn Sie Entitätseigenschaften, die keine Assoziationen sind, teilweise laden möchten, müssen Sie diese Doktrin explizit angeben:
Dadurch erhalten Sie ein teilweise geladenes Entitätsobjekt.
Beachten Sie jedoch, dass Teilobjekte keine Proxys sind! Lazy Loading gilt nicht für sie. Daher ist die Verwendung von Teilobjekten im Allgemeinen gefährlich und sollte vermieden werden. Lesen Sie mehr: Teilobjekte - Doctrine 2 ORM 2-Dokumentation
quelle