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

Symfony PHP Discussion :

[Doctrine] Error : Unknown relation alias - InnerJoin et relation n-n


Sujet :

Symfony PHP

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Inscrit en
    Juillet 2011
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2011
    Messages : 5
    Points : 5
    Points
    5
    Par défaut [Doctrine] Error : Unknown relation alias - InnerJoin et relation n-n
    Bonjour à tous,

    J'essaie de traduire une requête SQL à base de Inner Join avec Doctrine mais j'ai invariablement une erreur.
    Ma requête SQL fonctionne, mais pas sa transposition via Doctrine.

    Pour être plus précis, voici le schéma qui m'a permis de générer la DB :

    Code : 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
     
    Diu:
      columns:
        nom_diu: { type: string(255), notnull: true }
        (...)
     
    ##################################################
     
    Specialite:
      actAs:
        NestedSet:  
          hasManyRoots: true
          rootColumnName: root_id
      columns:
        nom_specialite:
          type: string(255)
          notnull: true
      relations:    #On définit ici la relation n-n entre la table des DIU et la table des Spéciliatés.
        Dius:       #On donne le nom de la relation, en utilisant le nom de la table liée au pluriel 
          foreignAlias: Specialites    #Alias optionnel correspondant à la table courante (nom au pluriel)
          class: Diu    #la classe (ie la table) qui est liée à Specialite
          refClass: DiuSpecialite  #Nom de la table intermédiaire
          local: specialite_id   #Référence à l'object courant (Specialite) avec le nom de la colonne le concernant dans DiuSpecialite
          foreign: diu_id  #Idem avec la table Diu
     
    DiuSpecialite:  #Définition de la table intermédiaire
      columns:
        diu_id: { type: integer, primary: true }
        specialite_id: { type: integer, primary: true }
      relations:
        Diu:
          onDelete: cascade  #le paramètre cascade permet de supprimer les lignes concernant soit une specialite soit un diu si celui-ci est supprimé.
          local: diu_id    #local représente la colonne de la table DiuSpecialite
          foreign: id      #foreign prend ici le nom de la colonne dans la table Diu (afin que Doctrine puisse faire le lien entreles clés primaires)
          foreignAlias: DiuSpecialites
        Specialite:
          onDelete: cascade
          local: specialite_id
          foreign: id
          foreignAlias: DiuSpecialites
    J'ai donc une table Diu, une table Specialite, et une table intermédiaire DiuSpecialite qui me sert de liaison dans ma relation n-n, un Diu pouvant recouvrir plusieurs spécialités, et une spécialité avoir plusieurs DIU.

    Je cherche à récupérer tous les DIU d'une spécialité ; ma requête SQL est donc celle-ci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    SELECT * FROM diu d
    INNER JOIN diu_specialite ds ON
    ds.diu_id = d.id
    INNER JOIN specialite s ON
    ds.specialite_id = s.id
    WHERE s.nom_specialite = 'Acupuncture'
    Cette requête fonctionne comme attendue, j'obtiens bien les éléments recherchés.

    En revanche j'ai plus de mal pour la traduction avec Doctrine... Voici ma requête :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    $this->liste=Doctrine_Query::create()
                    ->select('d.nom_diu')
                    ->from('Diu d')
                    ->innerJoin('DiuSpecialite ds ON ds.diu_id = d.id')
                    ->innerJoin('Specialite s ON s.id = ds.specialite_id')
                    ->where('s.nom_specialite = "Acupuncture"')
                    ->execute();
    Et j'ai alors le message d'erreur suivant :
    500 | Internal Server Error | Doctrine_Table_Exception
    Unknown relation alias

    avec entre autres les détails suivants :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    at ()
    in SF_ROOT_DIR/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Relation/Parser.php line 237 ...
     
                        return $this->getRelation($alias, false);
                    } else {
                        throw new Doctrine_Table_Exception('Unknown relation alias ' . $alias);
                    }
                }
    Je comprends donc qu'il y a un problème au niveau de la définition des relations et/ou de leur utilisation mais je vois pas bien lequel...

    J'aurais donc plusieurs questions :
    - Que dois-je changer dans ma requête Doctrine pour qu'elle fonctionne comme ma requête SQL ?
    - Est-ce un bon moyen de procéder pour effectuer cette requête ou y a t-il un moyen plus simple/efficace de faire (compte-tenue de ma relation n-n entre les 2 tables avec une table intermédiaire) ?

    Merci d'avance pour vos réponses

  2. #2
    Membre régulier
    Homme Profil pro
    Analyse système
    Inscrit en
    Mars 2011
    Messages
    444
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Analyse système

    Informations forums :
    Inscription : Mars 2011
    Messages : 444
    Points : 108
    Points
    108
    Par défaut
    essaye de redéfinir les relation dans tes Class (le dossier lib/doctrine/Diu.class.php) + les autre class de relation :
    par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class Facture extends BaseFacture
    {
    public function setUp() {
        	$this->hasOne(
        		'Mission',
        		array(
        			'local' => 'mission_idmission',
        			'foreign' => 'idmission'
        		)
        	);
    }
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class Mission extends BaseMission
    {
    public function setUp() {
    $this->hasMany(
        		'Facture',
        		array(
        			'local' => 'idmission',
        			'foreign' => 'mission_idmission'
        		)
        	);
    la requette est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
        function data() {
            $q = Doctrine_Query::create()
                    ->from('mission M')
                    ->innerJoin('M.Facture ET')
                    ->orderBy('M.idmission DESC');
            return $q->execute() ;
        }
    et c'est pareil pour les autre relation.et tu vide le cache symfony cc

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Inscrit en
    Juillet 2011
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2011
    Messages : 5
    Points : 5
    Points
    5
    Par défaut
    Merci pour ta réponse benhsaien.

    Cependant je ne pense pas que cela change grand chose puisque toutes ces relations ont déjà été définies dans les classes du dossier lib/model/doctrine/base/, générées automatiquement à partir du schema.

    Finalement en continuant mes recherches, je suis tombé sur ce post :
    http://groups.google.com/group/doctr...17c25024?fwc=1, et j'ai donc adapté la requête DQL de la sorte :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    $this->liste=Doctrine_Query::create()
                    ->select('d.nom_diu')
                    ->from('Diu d, d.DiuSpecialite ds, ds.Specialite s')
                    ->where('s.nom_specialite = "Acupuncture"')
                    ->execute();
    et... ça marche!
    La requête SQL correspondante effectuée est la suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    SELECT d.id AS d__id, d.nom_diu AS d__nom_diu 
    FROM diu d 
    LEFT JOIN diu_specialite d2 ON d.id = d2.diu_id 
    LEFT JOIN specialite s ON d2.specialite_id = s.id 
    WHERE (s.nom_specialite = "Acupuncture")
    Donc ça correspond bien à la requête que je cherchais à faire.

    Donc Doctrine effectue les jointures tout seul, sûrement en se basant sur les relations définies dans le schema. C'est donc beaucoup plus simple que ce que je pensais... même si ça semble un peu "magique"

    Cependant quelqu'un saurait-il m'expliquer pourquoi ma traduction DQL de la requête SQL ne fonctionnait pas ?
    Je me dis "si ça marche en SQL, a fortiori ça devrait marcher en DQL"...

  4. #4
    Expert éminent
    Avatar de Michel Rotta
    Homme Profil pro
    DPO
    Inscrit en
    Septembre 2005
    Messages
    4 954
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : DPO
    Secteur : Distribution

    Informations forums :
    Inscription : Septembre 2005
    Messages : 4 954
    Points : 8 486
    Points
    8 486
    Par défaut
    Ton schéma est presque bon, il ne faut en aucun cas aller modifier les relations générées dans les classes... très mauvaise idée.

    Tu peux réécrire la relation de la table Specialiste en supprimant les paramètres : local et foreign qui ne sont pas utilisé dans le cas d'une refClasse.

    En fait, ta requête en DQL est encore plus simple que ce que tu écris.
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    $this->liste=Doctrine_Query::create()
                    ->select('d.nom_diu')
                    ->from('Diu d)
                    ->innerJoin('d.specialistes s')
                    ->where('s.nom_specialite = "Acupuncture"')
                    ->execute();
    Tu peux donc faire totalement abstraction de la table intermédiaire dans la requête DQL.

    La méthode innerJoin() n'est pas le pendant exacte de la commande INNER JOIN du SQL. Sa syntaxe n'est donc pas équivalente. Ta deuxième écriture aurait pu coller dans des innerJoin().

    Effectivement, Doctrine se sert de ta description du modèle, si non, pourquoi s’embêter à la faire ?

    L'objectif du DQL est de permettre de simplifier l'écriture d'une requête, pas de singer le SQL, si non, le PDO suffirait amplement.
    Si tu donnes un poisson à un homme, il mangera un jour. Si tu lui apprends à pêcher, il mangera toujours (Lao Tseu).

    • Pensez à valoriser les réponses pertinantes, cliquez sur le bouton vert +1 pour indiquer votre accord avec la solution proposée.
    • Pensez à utiliser la balise [code] pour afficher du code, elle est cachée sous le bouton [#] dans l'éditeur.
    • Une discussion est terminée ? Alors le bouton est votre ami !

Discussions similaires

  1. [1.x] Unknown relation alias
    Par marwina32 dans le forum Symfony
    Réponses: 14
    Dernier message: 25/07/2011, 14h27
  2. [1.x] Unknown relation alias et innerJoin
    Par mysticpete dans le forum Symfony
    Réponses: 9
    Dernier message: 09/06/2011, 10h16
  3. [1.x] Unknown relation alias sfGuardUser
    Par YaNnZ dans le forum Symfony
    Réponses: 6
    Dernier message: 03/05/2011, 09h59
  4. [Doctrine] Erreur : "Unknown relation alias"
    Par lordlifen dans le forum ORM
    Réponses: 7
    Dernier message: 18/10/2010, 10h48
  5. Doctrine : inner join sans relations (alias)
    Par Lopimp dans le forum ORM
    Réponses: 8
    Dernier message: 26/03/2010, 02h30

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