Précédent   Forum des professionnels en informatique > PHP > Bibliothèques et frameworks > symfony
symfony Forum d'entraide sur le framework PHP symfony. Avant de poster : cours symfony et FAQ symfony
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 05/06/2011, 13h30   #1
Invité de passage
 
Inscription : janvier 2011
Messages : 11
Détails du profil
Informations forums :
Inscription : janvier 2011
Messages : 11
Points : 2
Points : 2
Par défaut Unknown relation alias et innerJoin

Bonjour,

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

Code :
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 :
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 :
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.
mysticpete est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/06/2011, 16h34   #2
Modérateur
 
Avatar de Michel Rotta
 
Homme Michel Rotta
Responsable d'exploitation informatique
Inscription : septembre 2005
Messages : 4 913
Détails du profil
Informations personnelles :
Nom : Homme Michel Rotta
Âge : 49
Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

Informations professionnelles :
Activité : Responsable d'exploitation informatique
Secteur : Distribution

Informations forums :
Inscription : septembre 2005
Messages : 4 913
Points : 7 505
Points : 7 505
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().
__________________
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 !
Michel Rotta est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/06/2011, 17h51   #3
Invité de passage
 
Inscription : janvier 2011
Messages : 11
Détails du profil
Informations forums :
Inscription : janvier 2011
Messages : 11
Points : 2
Points : 2
Pour relier les deux tables (objetsechange et annonces) j'ai rajouté la liaison dans ma BDD :

Code :
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 :
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 :
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()" ?)
mysticpete est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/06/2011, 19h15   #4
Modérateur
 
Avatar de Michel Rotta
 
Homme Michel Rotta
Responsable d'exploitation informatique
Inscription : septembre 2005
Messages : 4 913
Détails du profil
Informations personnelles :
Nom : Homme Michel Rotta
Âge : 49
Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

Informations professionnelles :
Activité : Responsable d'exploitation informatique
Secteur : Distribution

Informations forums :
Inscription : septembre 2005
Messages : 4 913
Points : 7 505
Points : 7 505
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 :
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 :
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 :
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.
__________________
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 !
Michel Rotta est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/06/2011, 19h47   #5
Invité de passage
 
Inscription : janvier 2011
Messages : 11
Détails du profil
Informations forums :
Inscription : janvier 2011
Messages : 11
Points : 2
Points : 2
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.
mysticpete est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/06/2011, 20h16   #6
Invité de passage
 
Inscription : janvier 2011
Messages : 11
Détails du profil
Informations forums :
Inscription : janvier 2011
Messages : 11
Points : 2
Points : 2
J'ai finalement réussi

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

Code :
1
2
3
4
5
6
  relations:
    Annonces:
      local: idAnnonceEchange
      foreign: idAnnonce
      type: one
      foreignAlias: ObjetEchange
et voilà ma requête :

Code :
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 ?
mysticpete est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/06/2011, 23h12   #7
Modérateur
 
Avatar de Michel Rotta
 
Homme Michel Rotta
Responsable d'exploitation informatique
Inscription : septembre 2005
Messages : 4 913
Détails du profil
Informations personnelles :
Nom : Homme Michel Rotta
Âge : 49
Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

Informations professionnelles :
Activité : Responsable d'exploitation informatique
Secteur : Distribution

Informations forums :
Inscription : septembre 2005
Messages : 4 913
Points : 7 505
Points : 7 505
Dans ton schema type: one est soit de trop, soit un peu seul, dans le cadre d'une relation 1-n, il ne sert à rien vu qu'il est valeur par défaut, il devrait être complété dans ce cas par un foreignType: many mais ces deux arguments n'ont d'intérêt que dans le cadre d'une relation 1-1. En effet, les relations n-n ont des déclarations particulières.

Notes que dans mon exemple, le foreignAlias est "ObjetEchanges", avec un "s" pour indiquer un retour d'un Doctrine_Collection.

Dans le cas où tu ne peux pas changer la structure de la base de données, il convient alors d'aménager au mieux le shema.yml pour qu'il colle à la base existante tout en te donnant un modèle exploitable. Tu peux même renommer les champs pour que tes propriétés colles.

Tu peux spécifier les modèles a régénéré, mais ceci ne présente aucun intérêt, tu as tout avantage à régénérer la totalité du modèle à chaque opération.
__________________
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 !
Michel Rotta est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/06/2011, 13h13   #8
Membre habitué
 
Inscription : juin 2006
Messages : 488
Détails du profil
Informations forums :
Inscription : juin 2006
Messages : 488
Points : 116
Points : 116
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.
erictomcat est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/06/2011, 08h22   #9
Modérateur
 
Avatar de Michel Rotta
 
Homme Michel Rotta
Responsable d'exploitation informatique
Inscription : septembre 2005
Messages : 4 913
Détails du profil
Informations personnelles :
Nom : Homme Michel Rotta
Âge : 49
Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

Informations professionnelles :
Activité : Responsable d'exploitation informatique
Secteur : Distribution

Informations forums :
Inscription : septembre 2005
Messages : 4 913
Points : 7 505
Points : 7 505
Tu as un exemple avec un bout de shema.yml ?
__________________
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 !
Michel Rotta est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/06/2011, 10h16   #10
Membre habitué
 
Inscription : juin 2006
Messages : 488
Détails du profil
Informations forums :
Inscription : juin 2006
Messages : 488
Points : 116
Points : 116
ma dernière tentative: http://www.developpez.net/forums/d10...lation-schema/
erictomcat est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 18h45.


 
 
 
 
Partenaires

Hébergement Web