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 :

Unknown relation alias et innerJoin [1.x]


Sujet :

Symfony PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 15
    Par défaut Unknown relation alias et innerJoin
    Bonjour,

    J'essaie de traduire en DQL une requête assez simple avec un innerJoin :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT DISTINCT objetsechange.idObjetEchange
    FROM annonces   
    INNER JOIN objetsechange ON objetsechange.idAnnonceEchange = annonces.idAnnonce
    En SQL la requête fonctionne... mais sur symfony le problème c'est que quoi que je fasse avec le "->innerJoin" je reçois toujours cette erreur 'Unknown relation alias'.

    La requête fait appel à deux tables.
    Voici la partie du schéma.yml correspondante :

    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
    Annonces:
      connection: doctrine
      tableName: annonces
      ..
      idannonce:
        type: integer(4)
        fixed: false
        unsigned: false
        primary: true
        autoincrement: true
      ...
      #Pas de relation avec Objetsechange
     
    Objetsechange:
      connection: doctrine
      tableName: objetsechange
      ..
      idobjetechange:
        type: integer(4)
        fixed: false
        unsigned: false
        primary: true
        autoincrement: true
      ...
      # Pas de relations avec Annonces
    Dans le schéma.yml les deux tables ne possèdent pas de relations. En SQL j'utilisais "ON objetsechange.idAnnonceEchange = annonces.idAnnonce" pour les relier manuellement.

    Ma requête :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $q = Doctrine_Query::create()
    ->select('DISTINCT Objetsechange.idobjetechange')
    ->from('Annonces')
    ->innerJoin(' ????? ');
    Que dois je faire pour pouvoir me servir de "->innerJoin" ?
    Quelqu'un pourrait-il me donner l'équivalent DQL de cette requête, que je comprenne mieux comment cela fonctionne ?

    Merci d'avance,
    bye.

  2. #2
    Expert confirmé
    Avatar de Michel Rotta
    Homme Profil pro
    DPO
    Inscrit en
    Septembre 2005
    Messages
    4 954
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    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
    Par défaut
    La méthode innerJoin() en DQL ne permet que d'utiliser les relations définies dans le modèle, d'où le message d'erreur retourné.

    Dans ton cas, il faut tout définir dans le from().

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 15
    Par défaut
    Pour relier les deux tables (objetsechange et annonces) j'ai rajouté la liaison dans ma BDD :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ALTER TABLE `objetsechange`
      ADD CONSTRAINT `objetsechange_ibfk_1` FOREIGN KEY (`idAnnonceEchange`) REFERENCES `annonces` (`idAnnonce`);
    J'ai regénérer le schéma.yml qui est maintenant le suivant :

    Annonces :

    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
    Annonces:
      connection: doctrine
      tableName: annonces
      columns:
        idannonce:
          type: integer(4)
          fixed: false
          unsigned: false
          primary: true
          autoincrement: true
       ...
      relations:
        Objetsechange:
          local: idannonce
          foreign: idannonceechange
          type: many
    Objetsechange :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    Objetsechange:
      connection: doctrine
      tableName: objetsechange
      ...
        idannonceechange:
          type: integer(4)
      ...
      relations:
        Annonces:
          local: idannonceechange
          foreign: idannonce
          type: one
    Quelle serait alors la bonne requête DQL ?
    (Sinon, que voulais tu dire par "tout définir dans le from()" ?)

  4. #4
    Expert confirmé
    Avatar de Michel Rotta
    Homme Profil pro
    DPO
    Inscrit en
    Septembre 2005
    Messages
    4 954
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    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
    Par défaut
    Bon... reprenons.

    Il est possible de définir des relations "sauvage" (pas définies dans le schéma) soit en les déclarant dans le from (avec un inner join on ) soit en déclarant les tables dans le form et la relation dans un where ou un andWhere. Ceci doit être strictement limités aux relations qui sont totalement étrangère au schéma et réellement exceptionnelles.

    Pour les autres... il convient au préalable de définir un schéma viable. Il existe deux méthodes pour définir le modèle objet de doctrine et la structure de la base de données, celle que tu utilises : définir la structure et en déduire un modèle et l'autre : définir un modèle et en déduire la structure. La seule bonne méthode est la deuxième, la première ne doit être utilisée que s'il n'est réellement pas possible d'envisager de faire autrement et, en réalité, il convient alors de jouer avec le shema pour coller au mieux à un modèle objet viable sans que la structure de la base de données (qui ne pourrait être modifiée dans ce cas) ne soit impacté.

    En partant de là et en fonction de ce que tu dis, je déduit que ton application est toute neuve, pas sèche pour un clou et que l'idéal est la seul bonne méthode : création d'un shema.yml qui va générer une base de données. Ceci va nous permettre d'avoir un modèle objet utilisable au mieux avec doctrine et pas de problèmes dans les relations entre les tables, ce qui, indirectement, va résoudre ton problème.

    Ton schéma réadapté pourrait donner un truc dans le genre :
    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
    # Exemple de shema.yml (non testé)
    Annonce: #Jamais de s à la fin d'un nom d'objet (ni de x).
      tableName: annonces
      columns:
         #l'id unique est auto généré et s'appel toujours id
       ... # Là, je ne peux pas trop commenter... 
     
     
    ObjetEchange:
      tableName: objetsechange
      ...
        annonce_id: #la liaison s'appel <nomDeLaTable>_id sauf exception (plusieurs liaisons par exemple)
          type: integer #L'id auto-généré est de type integer
      ...
      relations:
        Annonce:
          # local: annonce_id par défaut
          # foreign: id par défaut
          # le type est 1-n par défaut
          foreignAlias: ObjetEchanges 
            #Nom de la relation vue du côté de la table annonce
            #Avec un s vu qu'il y a plusieurs ObjetsEchange pour un annonce.
    Le DQL pour récupérer une annonce (id = $idMonAnnonce) ainsi que tous les objets échangé donne :
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    // exemple DQL pour récupérer les données (non testé)
    $data = Doctrine_query::create->
              from('Annonce a')->
              innerJoin('a.ObjetEchanges o')->
              where('a.id = ?', $idMonAnnonce )->
              fetchOne();

    On peut depuis $data récupérer les donnés des ObjetEchange par $data->getObjetEchanges() qui retourne un Doctrine_Collection. Le template qui permettrait d'afficher le nom de Annonce et le nom des ObjetEchange (pour peu qu'un champ name soit défini sur ces deux objets du modèle) donnerait plus ou moins :
    Code html : 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
    <!-- exemple de template (non testé) -->
    <section>
      <article>
        <h1>Annonce : <?php echo $data->getId() ?></h1>
        <p>Libellé :<?php echo $data->getName() ?></p>
        <h2>Liste des objets échangés</h2>
        <section>
          <?php foreach ($data->getObjetEchanges() as $ObjetEchange ): ?>
            <article>
              <h1>Objet : <?php echo $ObjetEchange->getId() ?></h1>
              <p>Nom de l'objet : <?php echo $ObjetEchange->getName() ?></p>
            </article>
          <?php endforeach ?>
        </section>
      </article>
    </section>
    Ceci est le code si l'hydratation de la requête est conservée en mode objet doctrine. Il peut être plus intéressant niveau performance de l'hydrater en array doctrine voir en simple array.

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 15
    Par défaut
    Tout d'abord merci pour le temps que tu prends à me répondre, c'est vraiment cool de ta part

    Malheureusement, je ne travaille pas sur un nouveau projet mais sur un site qui était entièrement codé en PHP procédurale. Celui-ci possède donc déjà une BDD mais qui est éventuellement modifiable cependant il n'est pas question de la recréer entièrement depuis un nouveau yml.

    Le système d'annonces et d'objets échangés ne fonctionnent pas exactement comme tu l'as mis (mais c'est normal tu n'as pas les yeux sur le projet !)
    En fait la relation ne s'effectue pas entre l'id de objetsEchange et l'id de Annonces mais entre idAnnonceEchange (qui est un autre id présent dans objetsEchange) et idAnnonce (dans Annonces).
    Une annonce possède UN SEUL objet échangé.

    Bref, je suis entrain de remodeler la BDD afin de pouvoir créer un YML viable, je vous tiens au courant.

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 15
    Par défaut
    J'ai finalement réussi

    J'ai ajouté dans mon schema.yml à ObjetsEchange

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
      relations:
        Annonces:
          local: idAnnonceEchange
          foreign: idAnnonce
          type: one
          foreignAlias: ObjetEchange
    et voilà ma requête :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $q = Doctrine_Query::create()
    ->select('a.idAnnonce')
    ->from('Annonces a')
    ->innerJoin('a.ObjetEchange o')
    Maintenant que j'ai compris, je vais pouvoir nettoyer la BDD et le schema

    Cependant j'ai une dernière question :

    Si je me rends compte à la moitié de mon projet que j'ai oublié une relation dans ma BDD et donc dans mon schéma, est-il possible de ne régénérer qu'une partie des models ? car "symfony doctrine:build-model' les recrée tous, non ?

  7. #7
    Membre éclairé
    Inscrit en
    Juin 2006
    Messages
    534
    Détails du profil
    Informations forums :
    Inscription : Juin 2006
    Messages : 534
    Par défaut
    Citation Envoyé par Michel Rotta Voir le message
    La méthode innerJoin() en DQL ne permet que d'utiliser les relations définies dans le modèle, d'où le message d'erreur retourné.

    Dans ton cas, il faut tout définir dans le from().
    je me permet de rebondir, malgré plusieurs tentatives, je n'ai jamais réussi à créer une relation qui n'était pas explicite dans le schéma.

  8. #8
    Expert confirmé
    Avatar de Michel Rotta
    Homme Profil pro
    DPO
    Inscrit en
    Septembre 2005
    Messages
    4 954
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    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
    Par défaut
    Tu as un exemple avec un bout de shema.yml ?

  9. #9
    Membre éclairé
    Inscrit en
    Juin 2006
    Messages
    534
    Détails du profil
    Informations forums :
    Inscription : Juin 2006
    Messages : 534

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

Discussions similaires

  1. [1.x] Unknown relation alias sfGuardUser
    Par etoileweb dans le forum Symfony
    Réponses: 2
    Dernier message: 04/01/2012, 10h59
  2. Réponses: 3
    Dernier message: 29/07/2011, 23h39
  3. [1.x] Unknown relation alias
    Par marwina32 dans le forum Symfony
    Réponses: 14
    Dernier message: 25/07/2011, 14h27
  4. [1.x] Unknown relation alias sfGuardUser
    Par YaNnZ dans le forum Symfony
    Réponses: 6
    Dernier message: 03/05/2011, 09h59
  5. [Doctrine] Erreur : "Unknown relation alias"
    Par lordlifen dans le forum ORM
    Réponses: 7
    Dernier message: 18/10/2010, 10h48

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