IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

ORM PHP Discussion :

Jointures imbriquées (userprofile, city, country) [Doctrine]


Sujet :

ORM PHP

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2011
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2011
    Messages : 18
    Points : 10
    Points
    10
    Par défaut Jointures imbriquées (userprofile, city, country)
    Bonjour à tous !

    J'essaie désespérément de créer une requête en DQL sous Doctrine 1.2 qui utilise des jointures imbriquées. La situation est simple : je pars d'une table userprofile qui est liée à une table city (via un city_id), qui est elle même liée à une table country (via un country_id).

    J'ai bien créé mes relations dans mon schema dont voici un extrait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    Userprofile:
      relations:
        City: { local: city_id, foreign: id, class: City }
     
    City:
      relations : 
        Country: { local: country_id, foreign: id, class: Country }
    Pour prendre un exemple, j'essaie de créer une requête qui permet d'obtenir le nom de l'utilisateur, ainsi que le nom de sa ville et de son pays.

    Voici les requêtes essayées qui ne fonctionnent pas :

    Requête 1 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
         $q = Doctrine_Query::create()
                ->select('p.id, p.username, c.name, co.name')
                ->from('Userprofile p, City c')
                ->innerJoin('c.Country co)'
                 ->where('p.city_id = c.id')
    Requête 2 (celle-ci, je comprends pourquoi elle ne fonctionne pas) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
         $q = Doctrine_Query::create()
                ->select('p.id, p.username, c.name, co.name')
                ->from('Userprofile p')
                ->innerJoin('p.City c)'
                ->innerJoin('c.Country co)'

    Requête 3 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
         $q = Doctrine_Query::create()
                ->select('p.id, p.username, c.name, co.name')
                ->from('Userprofile p Inner Join p.City c')
                ->innerJoin('c.Country co)'
    J'ai fait pas mal d'autres tests de requêtes mais j'aboutis toujours à la même erreur qui est :
    Couldn't find class co
    Bref, je vais faire comme d'habitude, la remplacer par une requête SQL qui fonctionnera correctement et qui me prendra 3 minutes à écrire. Mais l'objectif était d'utiliser le DQL, histoire de coder plus "proprement" mais visiblement ça ne paye pas toujours

    Merci pour votre aide !

    Nino

  2. #2
    Membre éclairé Avatar de kenny.kev
    Homme Profil pro
    Inscrit en
    Janvier 2007
    Messages
    646
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Janvier 2007
    Messages : 646
    Points : 816
    Points
    816
    Par défaut
    Alors déjà dans ce que tu donnes il n'y pas la classe Country.

    Voici un exemple de DQL :
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    $q = Doctrine_Query::create ()
            ->select ( 'p.*, h.uh_name, t.st_name, s.name_sst' )
            ->from ( 'SdsPatrolCmd p' )
            ->leftJoin('p.Host h')
            ->leftJoin('p.Sst s')
            ->leftJoin('p.St t');
    if (!empty ($where)) {
        $q->where ( $where, $paramWhere );
    }
    $q->limit ( $iLimit )->offset ( $iOffset );

    Voici le schéma :
    Code yaml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    Sst:
      tableName: SST
      relations:
        SdsPatrolCmd:
          local: id_sst
          foreign: id_sst
          type: many
    Host:
      tableName: HOST
      relations:
        Sts:
          local: uh_id
          foreign: uh_id
          class: St
          foreignAlias: Hosts
          refClass: UhSt
    St:
      tableName: ST
      relations:
        Hosts:
          local: st_id
          foreign: st_id
          class: Host
          foreignAlias: Sts
          refClass: UhSt
        SdsPatrolCmd:
          local: st_id_appli
          foreign: st_id
          type: many
    UhSt:
      tableName: UH_ST
      relations:
        St:
          foreignAlias: UhSts
          foreign: st_id
          local: st_id
        Host:
          foreignAlias: UhSts
          foreign: uh_id
          local: uh_id
    SdsProjectCmd:
      tableName: SDS_PROJECT_CMD
      relations:
        Sst:
          local: id_sst
          foreign: id_sst
          type: one
        Host:
          local: uh_id
          foreign: uh_id
          type: one

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2011
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2011
    Messages : 18
    Points : 10
    Points
    10
    Par défaut
    Bonjour,

    Dans mon exemple, la classe Country n'apparaît pas mais elle existe bien. Il n'y a pas de relation déclarée dans Country car c'est dans City que je déclare la relation à Country.

    Je n'ai pas compris ton exemple car la classe SdsPatrolCmd (dont il est fait référence dans ton FROM) n'existe pas dans ton schema, c'est le nom d'une relation de sst.

    Je suis surpris que personne d'autre ne réagisse sur cette problématique que j'ai rencontré plusieurs fois déjà. En SQL, tout fonctionne bien mais j'aimerais vraiment pouvoir utiliser les objets doctrine.

    un exemple tout simple du même type est que j'ai une table sfguarduser avec une relation vers sfguarduserprofile qui a une relation vers la table city. Si je veux lister les utilisateurs avec des infos du sfguarduser (username par exemple) + des infos personnalisées du sfguarduserprofile + le nom de sa ville, j'ai bien deux jointures consécutives et je n'arrive pas à la modéliser en DQL.

    Merci pour votre aide.

    Nino

  4. #4
    Membre éclairé Avatar de kenny.kev
    Homme Profil pro
    Inscrit en
    Janvier 2007
    Messages
    646
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Janvier 2007
    Messages : 646
    Points : 816
    Points
    816
    Par défaut
    Je me suis trompé avec le nom de la table, c'est pas SdsProjectCmd mais SdsPatrolCmd.

    Si tu ne comprends pas il te reste la doc de doctrine c'est exactement l'exemple de la doc :
    voici le lien :http://www.doctrine-project.org/proj...chema-files/nl

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2011
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2011
    Messages : 18
    Points : 10
    Points
    10
    Par défaut
    c'est ce que je pensais mais ça ne change rien à ma problématique. Dans ton exemple, la classe SdsPatrolCmd a des liens directs avec toutes les autres classes qui sont utilisées dans ta jointure.

    Dans mon exemple, j'ai une relation entre une table x vers y et de y vers z et j'essaie dans une seule requête DQL d'afficher des champs de ces 3 tables.

    J'ai bien une solution : ce serait d'ajouter un country_id à mon sfguarduserprofile et le tour est joué. Mais cette solution ne respecte pas les best practices de modélisation.

    Bref, j'ai compris comment on faisait du DQL même si je ne suis pas un grand connaisseur, d'où ma question sur le forum. J'ai des solutions mais aucune d'elles n'est "propre" et je ne trouve aucun exemple sur le net qui ne réponde à mon besoin.

    Ce que je pense et qui me surprend, c'est qu'il n'y a pas de solution avec Doctrine 1.2 pour le faire. Et si on me prouve le contraire, j'en serai vraiment heureux

    dans tous les cas, merci de m'avoir répondu, ça fait toujours avancer d'échanger sur les problématiques.

    Nino

  6. #6
    Membre éclairé Avatar de kenny.kev
    Homme Profil pro
    Inscrit en
    Janvier 2007
    Messages
    646
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Janvier 2007
    Messages : 646
    Points : 816
    Points
    816
    Par défaut
    Pardon j'ai mis le bon exemple.

    Mais je t'es mis presque toutes les bonne tables.
    Alors dans l'exemple j'ai une relation many to many entre Host et ST. d'ou m'a table UhSt.

    j'ai bien de x vers y et de y vers z.

    Et c'est la que doctrine est trop fort car pour que tu puisses avoir les données de la table tu as juste à faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ->leftJoin('p.Host h')
    ->leftJoin('h.St t')
    Et le tour est joué.
    Si c'est pas du many to many tu fait comme cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    ->leftJoin('p.Host h')
    ->leftJoin('h.Sst s')
    ->leftJoin('s.St t');
    et tu as une jointure standard ça te permet de pouvoir remonter les données des 3 tables.

    Bon courage.

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2011
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2011
    Messages : 18
    Points : 10
    Points
    10
    Par défaut
    Merci pour l'exemple, c'est ce qui me semble le plus logique pour les jointures imbriquées mais sauf erreur, j'ai déjà essayé cette méthode.

    Je fais le test très bientôt et je répondrai sur le forum.

    En tout cas, merci

    Nino

  8. #8
    Membre éclairé Avatar de kenny.kev
    Homme Profil pro
    Inscrit en
    Janvier 2007
    Messages
    646
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Janvier 2007
    Messages : 646
    Points : 816
    Points
    816
    Par défaut
    Si ça ne fonctionne pas c'est que tu as un problème sur les relations des tables dans le fichier schema.yml.

    Doctrine est assez sensible la dessus, le lien que j'ai fournit plus haut te permet de vérifier ta déclaration.

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2011
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2011
    Messages : 18
    Points : 10
    Points
    10
    Par défaut
    C'est génial, ça fonctionne !!!

    Et tu as raison, je pense avoir testé cette syntaxe en début de projet mais je n'avais pas le même schema qui n'était pas apprécié par Doctrine qui est très sensible.

    J'ai "normalisé" mon schema suite à des conseils sur les forums mais je n'avais pas retesté toutes les possibilités.

    J'ai souvent pesté contre Doctrine ces derniers mois et utilisé plus de SQL au détriment du DQL mais je me rends compte que tout était lié à la modélisation. Je remplacerai mes requêtes au fur et à mesure.

    Encore un grand merci.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Jointure imbriquée compliquée
    Par vidad10 dans le forum Requêtes
    Réponses: 4
    Dernier message: 05/08/2010, 09h00
  2. Probleme de Jointure imbriqué sur plusieurs tables
    Par cana13 dans le forum Langage SQL
    Réponses: 8
    Dernier message: 18/06/2009, 15h44
  3. Jointures imbriquées et jointures normales
    Par knowl dans le forum Développement
    Réponses: 5
    Dernier message: 24/10/2008, 23h44
  4. Pb de jointures imbriquées
    Par benjiiim dans le forum Langage SQL
    Réponses: 2
    Dernier message: 03/01/2008, 14h19
  5. Probleme de Jointures imbriquées dans une requête
    Par Crevin dans le forum Langage SQL
    Réponses: 3
    Dernier message: 13/04/2005, 11h05

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo