METTRE À JOUR
Cette réponse contient des informations erronées sur les différences entre les objets proxy et les objets partiels. Voir la réponse de @ Kontrollfreak pour plus de détails: https://stackoverflow.com/a/17787070/252591
Les objets proxy sont utilisés chaque fois que votre requête ne renvoie pas toutes les données requises pour créer une entité. Imaginez le scénario suivant:
@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
Comme vous pouvez le voir cette requête ne retourne pas firstname
et lastname
propriétés, donc vous ne pouvez pas créer User
objet. La création d'une entité incomplète peut entraîner des erreurs inattendues.
C'est pourquoi Doctrine créera un UserProxy
objet prenant en charge le chargement différé. Lorsque vous essayez d'accéder à la firstname
propriété (qui n'est pas chargée), il chargera d'abord cette valeur depuis la base de données.
Je veux dire pourquoi devrais-je utiliser un proxy?
Vous devez toujours écrire votre code comme si vous n'utilisiez pas du tout d'objets proxy. Ils peuvent être traités comme des objets internes utilisés par Doctrine.
Pourquoi le chargement différé ne peut pas être implémenté dans l'entité elle-même?
Techniquement, cela pourrait être mais jetez un œil à la classe d'un objet proxy aléatoire. C'est plein de code sale, pouah. C'est bien d'avoir un code propre dans vos entités.
Pouvez-vous me fournir un cas d'utilisation?
Vous affichez une liste des 25 derniers articles et vous souhaitez afficher les détails du premier. Chacun d'eux contient une grande quantité de texte, donc récupérer toutes ces données serait une perte de mémoire. C'est pourquoi vous ne récupérez pas de données inutiles.
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
Un proxy Doctrine n'est qu'un wrapper qui étend une classe d'entité pour lui fournir un chargement différé.
Par défaut, lorsque vous demandez au Gestionnaire d'entités une entité associée à une autre entité, l'entité associée ne sera pas chargée à partir de la base de données, mais encapsulée dans un objet proxy. Lorsque votre application demande alors une propriété ou appelle une méthode de cette entité mandatée, Doctrine chargera l'entité à partir de la base de données (sauf lorsque vous demandez l'ID, qui est toujours connu du proxy).
Cela se produit de manière totalement transparente pour votre application du fait que le proxy étend votre classe d'entité.
Doctrine hydrate par défaut les associations en tant que proxys de chargement différé si vous ne les faites pas
JOIN
dans votre requête ou si vous définissez le mode de récupération surEAGER
.Maintenant, je dois ajouter ceci car je n'ai pas assez de réputation pour commenter partout:
Malheureusement, la réponse de Crozin contient de la désinformation.
Si vous exécutez une requête DQL comme
vous n'obtiendrez pas un objet entité (mandaté), mais un tableau associatif. Il n'est donc pas possible de charger paresseusement des propriétés supplémentaires.
Dans cet esprit, on arrive à la conclusion que l'exemple de cas d'utilisation ne fonctionnera pas non plus. Le DQL devrait être changé en quelque chose comme ceci afin d'accéder en
$article
tant qu'objet:Et bien retourné par
getContent()
devrait être une association afin de ne pas charger les propriétés de contenu de toutes les 25 entités.Objets partiels
Si vous souhaitez charger partiellement des propriétés d'entité qui ne sont pas des associations, vous devez indiquer explicitement cette doctrine:
Cela vous donne un objet entité partiellement chargé.
Mais attention, les objets partiels ne sont pas des proxies! Le chargement différé ne s'applique pas à eux. Par conséquent, l'utilisation d'objets partiels est généralement dangereuse et doit être évitée. En savoir plus: Objets Partiels - Documentation Doctrine 2 ORM 2
la source