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 :

Resultat de requête many to many


Sujet :

Symfony PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Ingénieur d'études et de développement
    Inscrit en
    Juin 2009
    Messages
    112
    Détails du profil
    Informations professionnelles :
    Activité : Ingénieur d'études et de développement
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2009
    Messages : 112
    Par défaut Resultat de requête many to many
    Bonjour à tous !

    J'ai cherché sur le net et me suis arraché quelques cheveux mais sans trouver de solution :/
    Donc je viens vers vous ^^

    Voici mon problème :

    J'ai une table catégorie, une table item et une table data.
    Les relations entre les table sont les suivantes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    catégorie : n - n : items
    items : n - 1 : data
    On est en présence d'une relation many to many et d'une one to many. Entre les n-n il y a une table de mapping crée par Doctrine.
    Pour récupérer les items d'une catégorie j'effectue cette requête:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    $query = Doctrine_Query::create()
                ->select('c.name,i.name')
                ->from('Categorie c')
                ->leftJoin('c.MappingItem i')
                ->setHydrationMode(Doctrine_Core::HYDRATE_ARRAY);
    $data = $query->execute();
    Jusque là, pas de problème. J'arrive également à récupérer les data des items.
    Je peux également récupérer la catégorie, les items associés et les data associés aux items.

    Mon problèmes intervient lorsqu'une catégorie pointe vers plusieurs items et que les items pointent vers plusieurs data.
    Dans ce cas là, Doctrine est perdu et me sort tous les enregistrements de la base.
    Ce, même si je filtre avec un where.

    Exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Catégorie1 est mapée avec item1, item2 et item3
    Catégorie2 est mapée avec item2 et item3
    data1 et data3 pointent vers Item1
    data2 et data3 pointent vers Item3
    Si je demande la catégorie, les items et les data avec un where data = data3

    Je souhaite obtenir :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Categ1 -> item1 -> data3  
    Categ1 -> item3 -> data3  
    Categ2 -> item3 -> data3
    Mais j'obtiens:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Categ1 -> item1 -> data3 
    Categ1 -> item2 -> data3  <- erreur 
    Categ1 -> item3 -> data3
    Categ2 -> item2 -> data3  <- erreur
    Categ2 -> item3 -> data3
    Dès qu'un catégorie est mapée avec des items, tous les items de la catégorie sont récupérés :/

    Je ne sais pas trop comment m'en sortir.

    Merci d'avance pour votre aide.

  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
    Peux-tu mettre ton schéma ? 90% des problèmes viennent de là.

  3. #3
    Membre éprouvé
    Ingénieur d'études et de développement
    Inscrit en
    Juin 2009
    Messages
    112
    Détails du profil
    Informations professionnelles :
    Activité : Ingénieur d'études et de développement
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2009
    Messages : 112
    Par défaut
    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
    41
    42
    43
    44
    45
    46
    47
    48
    Category:
      actAs:
        NestedSet:
          hasManyRoots: true
          rootColumnName: root_id
      columns:
        name:
          type: string()
        type:
          type: string()
      relations:
        MappingItem:
          class: Item
          local: category_id
          foreign: item_id
          refClass: MappingFeatItem
     
    Item:
      columns:
        name:
          type: string()
        category_id:
          type: integer
      relations:
        Category:
          local: category_id
          foreign: id
          foreignAlias: Items
        MappingFeat:
          class: Category
          local: item_id
          foreign: category_id
          refClass: MappingFeatItem
        Data:
          local: id
          foreign: item_id
          type: many
     
    Data:
      columns:
        item_id:
          type: integer
          notnull: true
      relations:
        Item:
          local: item_id
          foreign: id
          type: one
    En fait il peut y avoir des variantes.

    Une data pointe vers un seul item. relation 1-n
    Exemple : trois utilisateurs utilisent l'item 'Stabilisation', il y aura donc trois data avec le même item_id mais avec un user_id différent.

    Un item peut pointer vers plusieurs catégorie ou une seule.
    Si il pointe vers une seule catégorie, j'utilise une relation 1-n avec une clé étrangère.
    Si il pointe vers plusieurs catégorie (que j'ai nommée 'feature') alors je passe par le mapping.

    Bien sur, les catégories elles peuvent contenir 1 à n item.

    Lors de mes requête, si je veux obtenir les catégories, leurs items associés et les data associées aux items. Je fais des leftJoin (j'ai également testé les innerJoin).
    Si une catégorie se retrouve plusieurs fois dans le mapping, alors je vais obtenir l'ensemble des items de cette catégorie. Bien que je puisse n'en vouloir que 2 (ceux qui correspondent à mon user)

    Merci Mimi68 une fois de plus de te pencher sur mon problème.
    Je suis actuellement en stage et j'ai une application assez complexe à développer avec Symfony Doctrine.
    Je connais relativement bien le Php mais je n'ai jamais utilisé Symfony et Doctrine. Le plus dur pour le moment et de créer une base qui puisse répondre à l'ensemble des requêtes que j'ai à lui fournir :/

  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
    Whaouuu

    Bon, manifestement le schéma te que tu me l'a présenté ne peux fonctionner correctement.

    Le problème c'est qu'il me semble qu'il manque des données et/ou des tables.

    Ensuite, tu sembles utiliser deux liaisons différentes entre Category et Item, ce qui me semble d'une complexité inutile.

    Si j'ai bien compris :

    La table catégorie est bâtie sous forme d'un arbre. Donc, en plus du reste, on peut avoir a rechercher les enfants d'une catégories, voir les Items en liaisons avec les enfants d'une catégorie.

    On est donc bien dans une liaison n-n entre Item et catégorie, chaque Item pouvant être rattachés à plusieurs catégories et chaque catégories pouvant représenter plusieurs item. Y a-t-il des limitations dans la manière dont un item peut être rattaché aux catégories (par exemple, s'il est lié à un parents, il ne peux plus être liés aux enfants...

    Il y a deux liaison entre item et catégorie, il faut supprimer cela c'est source d'erreurs et d'une complexité de traitement inutile.

    A quoi diable sert la table Data qui n'a qu'un champ de liaison ???

    Les relations ne doivent figurer que d'un côté de la relation, sur une des deux tables, surtout pas des deux côtés, c'est l'erreur assurée. Une seul exception les liaisons n-n qui requièrent 3 écritures de relations

    Dans la table category, il n'y a pas de taille pour les champs string.

    J'ai rajouté la table pour la liaison n-n category - item et les liens qui vont avec.

    Le schéma revu (et corrigé ?) (attention, il est possible qu'il y ait des tab qui soient dans le schéma, pas bon en yml. Je n'ai pas testé le chéma, mais il devrait être bon.
    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
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
     
    Category:
      actAs:
        NestedSet:
          hasManyRoots: true
          rootColumnName: root_id
      columns:
        name:
          type: string()
        type:
          type: string()
      relations:
        items:
    	  foreignAlias: categorys
    	  class: Item
              refClass: MappingFeatItem
     
    MappingFeatItem
      options:
        symfony:
    	  form: false
    	  filter: false
      columns:
        category_id: 
    	  type: integer
    	  primary: true
    	item_id
    	  type: integer
    	  primary: true
      relations:
        category:
    	  foreignAlias: MappingFeatItem
    	item
    	  foreignalias: MappingFeatItem
     
    Item:
      columns:
        name:
          type: string()
      relations:
        Data:
          local: id
          foreign: item_id
    	  foreignAlias: items
     
    Data:
      columns:
        item_id:
          type: integer
          notnull: true
        something: string(100)
    Pour un objet Category, on récupère les items par $category->getItems() qui retourne un Doctrine_Collection des Items rattachés à la catégorie (de 0 à n).

    Pour un $Item, tu peux récupérer la liste des catégories par $item->getCategorys(), là aussi un Doctrine_collection. Et le data rattaché à l'objet l'item par $item->getData() qui lui retourne directement un doctrine_record.

    Tu peux te contenter de récupérer un item par
    $q = Doctrine_Core::getTable('Item')->findOneById(4)

    Tu récupèreras toutes les autres données, catégories et data, au prix de 2 requêtes supplémentaires.

    Tu peux aussi tous récupérer d'un coup par :
    $q = Doctrine_Core::getTable('Item')->loadRelated('Date')->loadRelated('Category')->findOneById(4)
    devrait retourner les données en une seule requête (je ne suis pas sur pour les relation n-n.

    Si cela n'est pas ce que tu veux, ou ne fonctionne pas, tu sonnes à nouveau

  5. #5
    Membre éprouvé
    Ingénieur d'études et de développement
    Inscrit en
    Juin 2009
    Messages
    112
    Détails du profil
    Informations professionnelles :
    Activité : Ingénieur d'études et de développement
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2009
    Messages : 112
    Par défaut
    Merci pour ton aide.

    J'ai modifié le schéma car il y avait quelques bug ^^

    Quand je lance cette requête :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $q = Doctrine_Core::getTable('Item')->loadRelated('Data')->loadRelated('Category')->findOneById(4);
    j'ai une erreur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Unknown method ItemTable::loadRelated
    Pourtant en parcourant l'API de doctrine, j'ai constaté que c'est bien une fonction de Class Doctrine_Collection.

    Dans mon répertoire plugin je n'est rien.Mais j'ai quand même DoctrinePlugin d'activé par défaut.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class ProjectConfiguration extends sfProjectConfiguration
    {
      public function setup()
      {
        $this->enablePlugins('sfDoctrinePlugin');
      }
    }
    Bizare.

  6. #6
    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
    Dans Doctrine_collection, et c'est bien là qu'est le problème...

    Hors j'ai malencontreusement tenté de l'appliqué sur une requête.

    Donc le code avec loadRelated deviendrait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    $q = Doctrine_Core::getTable('Item')->findOneById(4);
    $q->loadRelated('Date');
    $q->loadRelated('Category');
    Soit trois requêtes...

    Autre possibilité en un coup et qui devrait marcher mieux.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    $q = Doctrine_Core::getTable('Item i')
         ->leftJoin('i.data d)
         ->leftJoin('i.categorys c)
         ->where('i.id = ?', 4)
         ->execute()
    (non testé)
    Ceci devrait être plus efficace, à défaut d'être aussi propre, et surtout de ce limiter à une requête.

Discussions similaires

  1. Requête hibernate many-to-many
    Par raff87 dans le forum Hibernate
    Réponses: 0
    Dernier message: 15/05/2009, 10h42
  2. Requête de selection sur table many to many
    Par doogy dans le forum Langage SQL
    Réponses: 3
    Dernier message: 04/05/2009, 19h44
  3. [EF] Sous-requête Where, Many-to-Many
    Par davcha dans le forum Accès aux données
    Réponses: 7
    Dernier message: 21/01/2009, 15h44
  4. Requête relation Many to Many
    Par alys56 dans le forum JPA
    Réponses: 1
    Dernier message: 20/04/2008, 12h20
  5. Un peu de mal a comprendre le concepte "one-to-many" et "many-to-many"
    Par chriscoolletoubibe dans le forum Hibernate
    Réponses: 4
    Dernier message: 29/03/2007, 18h50

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