116 votes

Ce qui est un Proxy dans Doctrine 2 ?

Je viens de terminer la lecture de toute la Doctrine 2 de la documentation, j'ai commencé mon propre bac à sable, j'ai compris la plupart des principes, mais il est encore une question et je ne pouvais pas trouver toutes les explications complètes dans la doc.

  1. Quelles sont Proxy des classes?
  2. Quand dois-je utiliser sur des entités?

Comme je le comprends, classes proxy ajouter une couche pour vous permettre d'ajouter d'autres fonctionnalités à vos entités, mais pourquoi utiliser un proxy au lieu de mettre en œuvre les méthodes elles-mêmes dans la classe d'entité?

160voto

Crozin Points 22346

Des objets Proxy sont utilisés à chaque fois que votre requête ne retourne pas de toutes les données nécessaires pour créer une entité. Imaginez 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 de firstname et lastname propriétés, donc il est impossible de créer User objet. Création d'incomplet entité pourrait conduire à des erreurs inattendues.

C'est pourquoi la Doctrine permettra de créer UserProxy objet qui prend en charge le chargement paresseux. Lorsque vous essayez d'accéder firstname de la propriété (ce qui n'est pas chargé), il va d'abord charger cette valeur à partir de la base de données.


Je veux dire, pourquoi devrais-je utiliser un proxy ?

Vous devriez toujours écrire votre code si vous n'utilisez pas de proxy objets à tous. Ils peuvent être traités comme des objets internes utilisés par la Doctrine.

Pourquoi le chargement paresseux ne peuvent pas être mis en œuvre dans le Entitiy lui-même?

Techniquement, il pourrait être, mais jetez un oeil à quelques aléatoire proxy classe de l'objet. C'est plein de sales code, pouah. C'est agréable d'avoir un code propre dans vos entités.

Pouvez-vous me donner un cas d'utilisation?

Vous êtes l'affichage d'une liste des dernières 25 articles et que vous souhaitez afficher un détail de la première. Chacun d'entre eux contiennent une grande quantité de texte, de sorte que l'extraction de toutes les données serait un gaspillage de mémoire. C'est pourquoi vous n'avez pas extraire 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;
    }
}

Mise à JOUR

Dans la section des commentaires ci-dessous, il est faux d'informations sur les différences entre les objets proxy et partielle des objets. Voir @Kontrollfreak réponses pour plus de détails: http://stackoverflow.com/a/17787070/252591

89voto

Kontrollfreak Points 557

Les procurations

Une Doctrine proxy est juste un wrapper qui étend une classe d'entité pour fournir le Chargement Paresseux pour cela.

Par défaut, lorsque vous demandez le Gestionnaire d'Entité dans une entité associée à une autre entité, l'entité associée ne sera pas chargé à partir de la base de données, mais enveloppé dans un objet proxy. Lorsque votre application demande une propriété ou appelle une méthode de ce proxy entité, Doctrine charge de l'entité de la base de données (sauf quand il vous demande le code, qui est toujours connu pour le proxy).

Ce qui se passe entièrement transparente à votre demande en raison du fait que le mandataire s'étend de votre classe d'entité.

La Doctrine, par défaut, l'hydrate d'associations de lazy load procurations si vous n'avez pas JOIN dans votre requête ou de définir le mode de lecture à l' EAGER.


Maintenant, je dois ajouter que cette car je n'ai pas assez de réputation pour commenter partout:

Malheureusement, Crozin la réponse contient la désinformation.

Si vous exécutez une requête DQL

SELECT u.id, u.username FROM Entity\User u WHERE u.id = :id

vous n'obtiendrez pas un (proxy) de l'entité objet, mais un tableau associatif. Il n'est donc pas possible de lazy load toutes les propriétés supplémentaires.

Avec cela à l'esprit, on en vient à la conclusion que le cas d'utilisation exemple ne fonctionne pas, soit. Le DQL devrait être modifié de quelque chose comme cela dans le but d'accéder $article comme objet:

SELECT a FROM Entity\Article a ORDER BY a.createdAt DESC LIMIT 25

Et la restitution des biens en getContent() devrait être une association afin de ne pas charger les propriétés du contenu de tous les 25 entités.


Partielle Des Objets

Si vous voulez charger partiellement propriétés d'entité qui ne sont pas des associations, vous avez à dire à cette Doctrine explicitement:

SELECT partial u.{id, username} FROM Entity\User u WHERE u.id = :id

Cela vous donne un partiellement chargé de l'entité de l'objet.

Mais méfiez-vous que la partielle des objets ne sont pas des procurations! Chargement différé ne s'applique pas à eux. Par conséquent, l'utilisation partielle des objets est généralement dangereux et doivent être évités. Lire la suite: Partielle des Objets - ORM Doctrine 2 2 documentation

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X