37 votes

Chargement paresseux avec Doctrine2 et Symfony2 en utilisant DQL

J'ai une structure arborescente avec un champ parent. Actuellement, je suis en train d'essayer d'obtenir tous les nœuds parents pour afficher le chemin d'accès du nœud actuel.

Fondamentalement, je suis en train de faire un boucle pour traiter tous les nœuds.

$current = $node->getParent();
while($current) {
  // do something
  $current = $current->getParent();
}

À l'aide de la valeur par défaut findById méthode fonctionne. Parce que l'entité a certains des champs agrégés, je suis en utilisant une mesure de référentiel méthode pour charger tous les champs de base avec une seule requête.

public function findNodeByIdWithMeta($id) {
    return $this->getEntityManager()
        ->createQuery('
            SELECT p, a, c, cc, ca, pp FROM
            TestingNestedObjectBundle:NestedObject p
            JOIN p.actions a
            LEFT JOIN p.children c
            LEFT JOIN c.children cc
            LEFT JOIN c.actions ca
            LEFT JOIN p.parent pp
            WHERE p.id = :id
        ')
        ->setParameter('id', $id)
        ->setHint(
            \Doctrine\ORM\Query::HINT_CUSTOM_OUTPUT_WALKER,
            'Gedmo\\Translatable\\Query\\TreeWalker\\TranslationWalker'
        )
        ->getOneOrNullResult();
}

Avec ce code, le chargement des parents échoue. Je ne reçois que le parent immédiat (adressée par LEFT JOIN p.parent pp), mais pas les parents ci-dessus. E. g. $node->getParent()->getParent() retours null.

Quoi de mal avec mon code? Ai-je mal compris le chargement paresseux chose?

Merci beaucoup, Hacksteak

7voto

tranver Points 393

Il ressemble au votre, sont à l'aide de la contiguïté modèle pour le stockage des arbres dans une base de données relationnelle. Qui à son tour signifie que vous aurez besoin d'une jointure pour chaque niveau pour obtenir tous les ancêtres avec une seule requête.

Comme vous êtes déjà à l'aide de la Doctrine de l'Extension de la Bibliothèque je recommande d'avoir un coup d'oeil à l' Arbre de la composante.

2voto

JustinP Points 547

Ma Réponse n'implique pas l'aide de DQL et au lieu de créer un NestedSetManager qui a accès à votre DBAL de connexion de sorte que vous pouvez utiliser SQL. Je n'ai jamais senti comme l'ORM du fait du bon travail avec NestedSets logique de requête.

Avec un NestedSetManager, vous pouvez alors écrire un tas de propres méthodes, et il est vraiment simple, car toutes ces requêtes sont bien documentés. Voir ce lien. Certains de la méthode dans mon NestedSetManager sont:

setNode();
setRoot();
loadNestedSet();
moveNodeUp();
modeNodeDown();
getRootNode();
addNodeSibling();
getNodesByDepth();
getParents();
getNodePath();
childExists();
addChildToNode();
renameNode();
deleteNode();
// And many more 

Vous pouvez avoir une boule et de créer beaucoup de créer NestedSet fonctionnalité si vous n'êtes pas lié par un ORM est un peu complexe fonctionnalité.

Aussi -- Symfony2 de tout cela, vraiment, vraiment facile. Vous créez votre NestedSetManager fichier de classe et de le référencer dans vos Services.yml et passer dans votre Dbal de connexion. Le mien ressemble à ça:

services:
    manager.nestedset:
        class: Acme\CoreBundle\Manager\NestedSetManager
        arguments: [ @database_connection ]

vous pouvez ensuite accéder à votre nestedsets avec:

$path = $this->get('manager.nestedset')->setNode(4)->getNodePath(); // in your controller

Morale de l'histoire, de l'ORM/NestedSets me rendait dingue et cette solution marche très bien. Si vous êtes forcé d'utiliser DQL et n'ont pas d'autres options, cette réponse probablement ne sera pas acceptable.

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