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

Schéma Discussion :

Bonnes pratiques pour modélisation d'une BD multilingue


Sujet :

Schéma

  1. #1
    Membre expérimenté

    Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2007
    Messages
    690
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juillet 2007
    Messages : 690
    Points : 1 478
    Points
    1 478
    Par défaut Bonnes pratiques pour modélisation d'une BD multilingue
    Bonjour !
    Voila, je viens à la pêche aux bonnes pratiques dans cette section de DVP

    J'ai une base de données à développer. Cette BD doit accepter du contenu venant de plusieurs pays, donc plusieurs langues. Par exemple, pour une description de produit, j'aurais une description en anglais, en français, en allemand, en arabe, etc.
    J'aimerais connaitre les bonnes pratiques pour la conception de telles bases (un peu comme le site de Amazon). J'ai déjà identifié quelques options :
    1- Une colonne par langue : rapide mais pas très évolutif (si je veux ajouter une nouvelle langue + taille de la base quasi doublé à chaque nouvelle langue).
    2- Les champs textes seront en fait une clé étrangère vers une table de "traduction" avec idTexte, langue, valeur : potentiels problèmes de performance.
    3- Ajouter la langue dans la déf de clé primaire de chaque table : pas propre, on veut gérer des produits et pas des langues...

    J'aimerais vos avis et idées.

    Merci !

  2. #2
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 001
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 001
    Points : 30 905
    Points
    30 905
    Billets dans le blog
    16
    Par défaut
    Bonsoir,


    A la très grande louche, à 100 km d’altitude et d'un point de vue tabulaire :

    Supposons que la table Produit "monolingue" ait la structure suivante, dans la quelle l’attribut ProdId représente la clé primaire du produit, l’attribut ProdLibelle la désignation du produit, ProdAtt1, ProdAtt2, etc. les autres attributs de Produit (clé primaire soulignée) :
    Produit (ProdId, ProdLibelle, ProdAtt1, ProdAtt2, ProdAtta3, ProdAtt4, ProdAtta5, ..., ProdAttn)
    Dans la mesure où l’attribut ProdLibelle ainsi par exemple que les attributs ProdAtt3 et ProdAtt4 deviennent multivalués du fait du passage à une version multilingue de la table Produit, pourquoi ne pas mettre en œuvre une table de référence Langue (évidemment unique pour la base de données) et éjecter vers une table ProduitLangue les attributs ProdLibelle, ProdAtt3 et ProdAtt4 ?
    Produit (ProdId, ProdAtt1, ProdAtt2, ProdAtta5, ..., ProdAttn)

    ProduitLangue (ProdId, LangueId, ProdLibelle, ProdAtta3, ProdAtt4)

    Langue (LangueId, LangueAtt1, ..., LangueAttn)
    Dans la table ProduitLangue, les attributs ProdId et LangueId composent la clé primaire, mais composent aussi respectivement les clés étrangères référençant les tables Produit et Langue.

    Naïvement, je dirai que les valeurs prises par les attributs ProdLibelle, ProdAtta3, ProdAtt4 sont exprimées dans la langue qui va bien.

    Quelque part, on retrouve ici les problèmes que l'on rencontre avec les propriétés multivaluées, cas par exemple des historiques.
    (a) Faites simple, mais pas plus simple ! (A. Einstein)
    (b) Certes, E=mc², mais si on discute un peu, on peut l’avoir pour beaucoup moins cher... (G. Lacroix, « Les Euphorismes de Grégoire »)
    => La relativité n'existerait donc que relativement aux relativistes (Jean Eisenstaedt, « Einstein et la relativité générale »)

    __________________________________
    Bases de données relationnelles et normalisation : de la première à la sixième forme normale
    Modéliser les données avec MySQL Workbench
    Je ne réponds pas aux questions techniques par MP. Les forums sont là pour ça.

  3. #3
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Je ne sais pas pourquoi tu éjectes ProdAtta3, ProdAtt4 puisqu'il ne te parle que du libellé mais la solution est bien celle-là, c'est à dire l'option 2 à laquelle il avait pensé.
    Quant aux problèmes de performances, pas d'affolement avec ça. Il faut vraiment de gros volumes pour que les jointures deviennent pénalisantes en terme de performances.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  4. #4
    Membre expérimenté

    Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2007
    Messages
    690
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juillet 2007
    Messages : 690
    Points : 1 478
    Points
    1 478
    Par défaut
    Merci beaucoup pour vos conseils. J'opterais donc pour la solution décrite par Monsieur Smerl.

  5. #5
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 001
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 001
    Points : 30 905
    Points
    30 905
    Billets dans le blog
    16
    Par défaut
    Citation Envoyé par CinePhil Voir le message
    Je ne sais pas pourquoi tu éjectes ProdAtta3, ProdAtt4 puisqu'il ne te parle que du libellé
    Simplement parce que j’ai écrit, histoire de généraliser :
    Dans la mesure où l’attribut ProdLibelle ainsi par exemple que les attributs ProdAtt3 et ProdAtt4 deviennent multivalués du fait du passage à une version multilingue.


    Citation Envoyé par CinePhil Voir le message
    Quant aux problèmes de performances, pas d'affolement avec ça. Il faut vraiment de gros volumes pour que les jointures deviennent pénalisantes en terme de performances
    Même des jointures sur des tables de cent millions de lignes ne sont pas pénalisantes si les requêtes sont filtrantes. Même chose si l’effet cluster joue plein pot (en l’occurrence sur l'attribut ProdId concernant la jointure entre Produit et ProduitLangue, la jointure entre Langue et ProduitLangue sur LangueId comptant pour du beurre, du fait de la très faible volumétrie de la table Langue). En tout cas cela vaut pour DB2 for z/OS. Pour les autres SGBD, à vérifier.
    (a) Faites simple, mais pas plus simple ! (A. Einstein)
    (b) Certes, E=mc², mais si on discute un peu, on peut l’avoir pour beaucoup moins cher... (G. Lacroix, « Les Euphorismes de Grégoire »)
    => La relativité n'existerait donc que relativement aux relativistes (Jean Eisenstaedt, « Einstein et la relativité générale »)

    __________________________________
    Bases de données relationnelles et normalisation : de la première à la sixième forme normale
    Modéliser les données avec MySQL Workbench
    Je ne réponds pas aux questions techniques par MP. Les forums sont là pour ça.

  6. #6
    Futur Membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 5
    Points : 6
    Points
    6
    Par défaut
    Bonsoir à tous,
    J'aimerai donner suite à cette discussion commencée en 2008 ().
    Je suis actuellement entrain de développer un site web multilingue. J'utilise la même logique de conception des tables que fsmrel :
    - Produit (idProduit, ProdAtt1, ProdAtt2)
    - ProduitLangue (idProduit, idLangue, ProdLibelle)
    - Langue (idLangue, LangueLibelle)
    En poursuivant sur cet exemple, je souhaiterais maintenant créer l'objet métier "Produit". Cet objet doit donc être traduit dans plusieurs langues différentes. Je propose de créer cet objet comme suit :
    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
    class Produit
    {
        private $idProduit;
        private $ProdLibelle;
        private $ProdAtt1;
        private $ProdAtt2;
        private $langue; //objet langue
        //constructeur...
        //getters-setters ...
    }
    
    class Langue
    {
        private $idLangue;
        private $langueLibelle;
        //constructeur / getters-setters ...
    }
    Cependant, je m’interroge sur cet objet :
    - Si l’on souhaite afficher la liste des produits avec la liste des langues dans lesquelles ils sont traduits.
    ex. :
    idProduit | ProdLibelle | ProdAtt1 | ProdAtt2 | Langues
    #1 | nom1 | att1 | att2 | fr,en,ita
    #2 | nom2 | att1a | att2a | fr

    Avec notre objet actuel, nous aurions plusieurs fois le même objet Produit traduit dans diverses langues et n’ayant aucune relation entre eux.

    La requête SQL nous renvoie :
    1,nom1,att1,att2,fr
    1,name1,att1,att2,en
    1,nome1,att1,att2,ita
    2,nom2,att1a,att2a,fr

    Le fait d’avoir plusieurs objets pour représenter le même produit traduit dans différentes langues me gêne un peu. Qu’en pensez-vous ?

    Une solution pourrait être de transformer notre objet produit en y ajoutant un tableau de Produit_Traduction (objet créé pour l’occasion) contenant les champs à internationaliser. Cette solution me parait un peu farfelue. Qu’en pensez-vous ?

    Je manque cruellement d’expérience dans ce domaine, comment auriez-vous fait ?
    De plus, je me pose des questions sur la gestion des traductions. Comment administrez-vous vos sites multilingues (ex. : pour l’ajout et la gestion des traductions d’un produit) ?
    Je vous remercie d’avance,
    Bonne soirée.

  7. #7
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 001
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 001
    Points : 30 905
    Points
    30 905
    Billets dans le blog
    16
    Par défaut
    Bonsoir pass1,


    Citation Envoyé par pass1 Voir le message
    La requête SQL nous renvoie :
    1,nom1, att1, att2, fr
    1,name1, att1, att2,en
    1,nome1, att1, att2, ita
    2,nom2, att1a, att2a,fr
    Si vous voulez obtenir ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    idProduit   ProdLibelle   ProdAtt1   ProdAtt2   Langues 
        #1         nom1         att1       att2     fr, en, ita
        #2         nom2         att1a      att2a    fr
    alors cela veut dire que la 1re requête ne convient pas et qu’il faut en écrire une autre, mais sans toucher bien sûr à la structure des tables...

    Considérons donc les structures suivantes :

    Code D : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    PRODUIT {IdProduit, ProdAtt1, ProdAtt2}
         PRIMARY KEY {IdProduit} ;
    
    LANGUE {IdLangue, LangueLibelle}
         PRIMARY KEY {IdLangue} ;
    
    PRODUIT_LANGUE {IdProduit, IdLangue, ProdLibelle}
         PRIMARY KEY {IdProduit, IdLangue}
         FOREIGN KEY {IdProduit} REFERENCES PRODUIT ;
         FOREIGN KEY {IdLangue} REFERENCES LANGUE ;

    Dans la mesure où, pour chaque produit, vous souhaitez produire la liste des langues, non pas sur autant de lignes qu’il y a de langues pour le produit, mais sur une seule ligne, quelque part on s’embarque pour développer une requête récursive...

    Considérons les lignes suivantes de la table PRODUIT_LANGUE :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    IdProduit, IdLangue, ProdLibelle
      p01        l01     Cigares        // français
      p01        l02     Cigars         // anglais
      p01        l03     Sigari         // italien
    Dans un contexte récursif, l’idée est, pour chaque produit, de concaténer le nom de la langue de chaque IdLangue avec le précédent et d’encapsuler le tout dans une vue. Le code SQL (avec SQL Server) pourrait être le suivant (on s’accroche, mais j’ai numéroté les lignes pour expliquer...) :

    Code SQL : 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
    01  CREATE VIEW VUE_PRODUIT (IdProduit, ProdLibelle, ProdAtt1, ProdAtt2, Langues) AS
    02  WITH VueRecursive (IdProduit, IdLangue, Langues, NoOrdre) AS
    03 (
    04     SELECT x.IdProduit, x.IdLangue, CAST(z.LangueLibelle AS VARCHAR(512)), 1
    05     FROM   PRODUIT_LANGUE AS x 
    06            JOIN
    07                  (SELECT IdProduit, MIN(IdLangue) AS IdLangue
    08                   FROM   PRODUIT_LANGUE
    09                   GROUP BY IdProduit) AS y
    10               ON  x.IdProduit = y.IdProduit
    11               AND x.IdLangue = y.IdLangue
    12            JOIN LANGUE AS z
    13               ON  y.IdLangue = z.IdLangue 
    14    UNION ALL
    15     SELECT x.IdProduit, 
    16            y.IdLangue, 
    17            CAST (x.Langues + ', ' + z.LangueLibelle AS VARCHAR(512)),
    18            NOordre + 1
    19     FROM   VueRecursive AS x 
    20            JOIN PRODUIT_LANGUE AS y
    21               ON  x.IdProduit = y.IdProduit  
    22               AND x.IdLangue < y.IdLangue
    23            JOIN LANGUE AS z
    24               ON  y.IdLangue = z.IdLangue 
    25  )
    26  SELECT x.IdProduit, z.ProdLibelle, u.ProdAtt1, u.ProdAtt2, x.Langues 
    27  FROM   VueRecursive AS x 
    28         JOIN 
    29             (SELECT IdProduit, MAX(NoOrdre) AS NoOrdre
    30              FROM   VueRecursive  
    31              GROUP BY IdProduit) AS y 
    32            ON x.IdProduit = y.IdProduit
    33            AND x.NoOrdre = y.NoOrdre
    34          JOIN PRODUIT_LANGUE AS z
    35            ON  y.IdProduit = z.IdProduit
    36          JOIN LANGUE AS t
    37            ON z.IdLangue = t.IdLangue
    38          JOIN PRODUIT AS u
    39            ON z.IdProduit = u.IdProduit
    40  WHERE t.LangueLibelle = 'français'   
    41  GO 

    Pour obtenir le résultat complet :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT * 
    FROM   VUE_PRODUIT
    ORDER BY IdProduit

    Explication de la vue :

    Ligne 01 : On définit la structure de la vue, qui peut alors être manipulée comme une table (c’est une table virtuelle).

    Lignes 02 à 25 : Union récursive pour concaténer les langues.

    Lignes 26 à 40 : Une fois constitué le résultat de la concaténation des langues, récupération de ce résultat et des autres données dans les diverses tables.

    Partie récursive (lignes 02 à 25). Cette partie est ainsi constituée :

    Ligne 02 : déclaration de la vue récursive VueRecursive.

    Lignes 04 à 13 : Amorçage de la pompe. Pour chaque produit, on récupère la valeur de l’attribut IdProduit pour lequel la valeur de l’attribut IdLangue est la plus petite.

    Ligne 04 : La fonction CAST permet de typer le libellé de la langue selon les critères imposés par l’union récursive. Le chiffre 1 permet d’initialiser la numérotation des lignes qui figureront dans le résultat (attribut NoOrdre).

    Ligne 07 : pour chaque produit, on récupère la ligne correspondant à la langue pour laquelle la valeur de l’attribut IdLangue est le plus petit.

    Ligne 14 : couplé avec le WITH de la ligne 02, l’opérateur UNION ALL est le signal de l’union récursive. Les lignes qui suivent décrivent le processus récursif proprement dit : jointure de la vue VueRecursive avec la table PRODUIT_LANGUE et avec la table LANGUE, pour récupérer les langues non encore récupérées.

    Ligne 17 : concaténation d’une ligne de la vue et d’un libellé de langue non encore récupéré.

    Ligne 18 : numérotation des lignes récupérées dans VueRecursive.

    Lignes 21-22 : jointure sur IdProduit et IdLangue. Le test d’infériorité permet de ne pas récupérer ce qui l’est déjà.

    Lignes 26 à 40 : le traitement récursif est terminé.

    Ligne 29 : pour chaque produit, on ne conserve que la dernière concaténation, les autres n’étant que des résultats intermédiaires.

    Ligne 40 : on suppose que le libellé du produit qui nous intéresse est celui qui est en français.

    Exemple de résultat obtenu :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    IdProduit   ProdLibelle   ProdAtt1   ProdAtt2   Langues
       p01      Cigares         a11        a12      français, anglais, italien
       p02      Chaussures      a21        a22      français

    N.B. J'ai fait dans le brutal. Les cracks de SQL ont sans doute des solutions plus conviviales à proposer...

    Par ailleurs, en fonction de votre SGBD, il peut y avoir des aménagements (fonction de concaténation, etc.) à effectuer dans l'organisation de la requête. En tout cas, on ne touche pas à la structure des tables, on passe par des vues qui après tout sont des tables virtuelles...
    (a) Faites simple, mais pas plus simple ! (A. Einstein)
    (b) Certes, E=mc², mais si on discute un peu, on peut l’avoir pour beaucoup moins cher... (G. Lacroix, « Les Euphorismes de Grégoire »)
    => La relativité n'existerait donc que relativement aux relativistes (Jean Eisenstaedt, « Einstein et la relativité générale »)

    __________________________________
    Bases de données relationnelles et normalisation : de la première à la sixième forme normale
    Modéliser les données avec MySQL Workbench
    Je ne réponds pas aux questions techniques par MP. Les forums sont là pour ça.

  8. #8
    Futur Membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 5
    Points : 6
    Points
    6
    Par défaut
    Bonsoir,
    Je vous remercie de votre réponse fsmrel, effectivement ce n'est pas si simple à appréhender. Cependant, cela ne répond pas entièrement à ma question qui était au sujet des objets métiers (l'objet "produit" essentiellement).
    Cdt,
    P.

    Edit:Je ne me trouve peut être pas dans le bon forum.

  9. #9
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 001
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 001
    Points : 30 905
    Points
    30 905
    Billets dans le blog
    16
    Par défaut
    Quelle est plus précisément votre question ?

    Vous disposez de la table LANGUE et de la table VUE_PRODUIT (dérivée, mais table du point de vue des applications) ayant respectivement les structures suivantes (en correspondance avec les attributs de vos classes) :
    LANGUE {IdLangue, LangueLibelle}
    VUE_PRODUIT {IdProduit, ProdLibelle, ProdAtt1, ProdAtt2, Langues}
    La table LANGUE est-elle sans emploi pour votre classe Langue ?

    La table VUE_PRODUIT est-elle sans emploi pour votre classe Produit ? Préférez-vous que l’attribut Langues soit constitué non pas du libellé de chaque langue décrivant le produit, mais de leur identifiant ?
    (a) Faites simple, mais pas plus simple ! (A. Einstein)
    (b) Certes, E=mc², mais si on discute un peu, on peut l’avoir pour beaucoup moins cher... (G. Lacroix, « Les Euphorismes de Grégoire »)
    => La relativité n'existerait donc que relativement aux relativistes (Jean Eisenstaedt, « Einstein et la relativité générale »)

    __________________________________
    Bases de données relationnelles et normalisation : de la première à la sixième forme normale
    Modéliser les données avec MySQL Workbench
    Je ne réponds pas aux questions techniques par MP. Les forums sont là pour ça.

  10. #10
    Futur Membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 5
    Points : 6
    Points
    6
    Par défaut
    Bonjour fsmrel,
    Pour faire simple, je voulez avoir votre avis sur la construction de ma classe "Produit".
    S'il était préférable :
    • Inclure un attribut langue (objet langue construit effectivement grâce à ma table langue)

    • Inclure un tableau d'un objet créé pour l'occasion (produit_traduction) qui contiendrait tous les champs à internationaliser en plus de l'objet langue

    • une autre solution...


    Première proposition :
    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
    class Produit
    {
        private $idProduit;
        private $ProdLibelle;
        private $ProdAtt1;
        private $ProdAtt2;
        private $langue; //objet langue
        //constructeur...
        //getters-setters ...
    }
    
    class Langue
    {
        private $idLangue;
        private $langueLibelle;
        //constructeur / getters-setters ...
    }
    Seconde proposition :
    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
    class Produit
    {
        private $idProduit;
        
        private $ProdAtt1;
        private $ProdAtt2;
        private $arrayProduit_Trad; //tableau d'objet Produit_Trad
    
        //constructeur...
        //getters-setters ...
    }
    
    class Produit_Trad
    {
        private $ProdLibelle;
        private $langue // objet Langue
    }
    
    class Langue
    {
        private $idLangue;
        private $langueLibelle;
        //constructeur / getters-setters ...
    }

    Sachant que dans le backend de mon application, je souhaitais afficher une liste de produit qui aurait cette forme :
    idProduit ProdLibelle ProdAtt1 ProdAtt2 Langues
    #1 nom1 att1 att2 fr, en, ita
    #2 nom2 att1a att2a fr
    Dans ce cas :
    • En utilisant la première proposition j'aurai 4 objets Produit

    • En utilisant la seconde proposition j'aurai 2 objets Produit (ce qui parait plus logique). Cependant la création de l'objet Produit_Traduction me semble un peu étrange.


    J'espère avoir été plus clair.
    Cdt,
    P.

    ------------------
    Edit :

    La seconde proposition représentée par un diagramme de classe :

    Il y aurait une composition entre l'objet Produit et Produit_Langue.

  11. #11
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 001
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 001
    Points : 30 905
    Points
    30 905
    Billets dans le blog
    16
    Par défaut
    Bonsoir,

    Il y a comme un quiproquo...


    Je reprends au début. Vous écrivez :

    Citation Envoyé par pass1 Voir le message
    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
     
    class Produit
    {
        private $idProduit;
        private $ProdLibelle;
        private $ProdAtt1;
        private $ProdAtt2;
        private $langue; //objet langue
        //constructeur...
        //getters-setters ...
    }
    
    class Langue
    {
        private $idLangue;
        private $langueLibelle;
        //constructeur / getters-setters ...
    }
    Cependant, je m’interroge sur cet objet :
    - Si l’on souhaite afficher la liste des produits avec la liste des langues dans lesquelles ils sont traduits.
    ex. :
    idProduit | ProdLibelle | ProdAtt1 | ProdAtt2 | Langues
    #1 | nom1 | att1 | att2 | fr,en,ita
    #2 | nom2 | att1a | att2a | fr

    Avec notre objet actuel, nous aurions plusieurs fois le même objet Produit traduit dans diverses langues et n’ayant aucune relation entre eux.

    La requête SQL nous renvoie :
    1,nom1,att1,att2,fr
    1,name1,att1,att2,en
    1,nome1,att1,att2,ita
    2,nom2,att1a,att2a,fr

    Le fait d’avoir plusieurs objets pour représenter le même produit traduit dans différentes langues me gêne un peu.
    SI vous avez utilisé une requête SQL pour obtenir ce résultat, c’est que vous quittez le niveau conceptuel pour vous situer au niveau de ce langage, donc que vous avez produit des structures de tables ressemblant à celles-ci (et dérivables à partir du diagramme de classes que vous avez fourni) :
    Code SQL : 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
    CREATE TABLE PRODUIT
    (
            IdProduit      INT              NOT NULL
          , ProdAtt1       VARCHAR(32)      NOT NULL
          , ProdAtt2       VARCHAR(32)      NOT NULL
      , CONSTRAINT PRODUIT_PK PRIMARY KEY (IdProduit) 
    ) ;
    CREATE TABLE LANGUE
    (
            IdLangue       INT              NOT NULL
          , LangueLibelle  VARCHAR(32)      NOT NULL
          , langAtt1       VARCHAR(32)      NOT NULL
          , LangAtt2       VARCHAR(32)      NOT NULL
      , CONSTRAINT LANGUE_PK PRIMARY KEY (IdLangue) 
    ) ;
    CREATE TABLE PRODUIT_LANGUE
    (
            IdProduit      INT              NOT NULL
          , IdLangue       INT              NOT NULL
          , ProdLibelle    VARCHAR(32)      NOT NULL
      , CONSTRAINT PRODUIT_LANGUE_PK PRIMARY KEY (IdProduit, IdLangue) 
      , CONSTRAINT PRODUIT_LANGUE_FK1 FOREIGN KEY (IdProduit)
           REFERENCES PRODUIT 
      , CONSTRAINT PRODUIT_LANGUE_FK2 FOREIGN KEY (IdLangue)
           REFERENCES LANGUE 
    ) ;

    Reprenons votre résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    idProduit  ProdLibelle  ProdAtt1  ProdAtt2  LangueLibelle
        1         nom1         att1      att2         fr
        1         name1        att1      att2         en
        1         nome1        att1      att2         ita
        2         nom2         att1a     att2a        fr
    Alors pour le produire, vous avez utilisé une requête équivalente à celle-ci :
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    SELECT  x.idProduit, y.ProdLibelle, x.ProdAtt1, x.ProdAtt2, z.LangueLibelle
    FROM    PRODUIT AS x JOIN PRODUIT_LANGUE AS y ON x.idProduit = y.IdProduit
                         JOIN LANGUE AS z ON y.idLangue = z.idLangue ;

    Maintenant, ce résultat ne vous convenant pas puisque vous dites préférer le suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    idProduit  ProdLibelle  ProdAtt1  ProdAtt2  Langues
        1         nom1        att1      att2    fr, en, ita
        2         nom2        att1a     att2a   fr
    Alors, je le répète, à cette fin, utilisez la requête suivante :
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    SELECT  idProduit, ProdLibelle, ProdAtt1, ProdAtt2, Langues
    FROM    VUE_PRODUIT ;

    Je note toutefois que si l’on interprète votre exemple, alors il est demandé de fournir la liste des langues par produit. Si vous voulez plutôt avoir la liste des noms du produit dans les différentes langues :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    idProduit  ProdLibelle  ProdAtt1  ProdAtt2  Langues
        1         nom1        att1      att2    nom1 (fr), name1(en), nome1(ita)
        2         nom2        att1a     att2a   nom1 (fr)
    Alors la requête utilisée par la table dérivée VUE_PRODUIT doit être aménagée ainsi :

    Ligne 04 : remplacer
    z.LangueLibelle
    par
    y.ProdLibelle + ' (' + z.LangueLibelle + ')'
    Ligne 07 : remplacer
    SELECT IdProduit, MIN(IdLangue) AS IdLangue
    par
    SELECT IdProduit, ProdLibelle, MIN(IdLangue) AS IdLangue
    Ligne 09 : remplacer
    GROUP BY IdProduit
    par
    GROUP BY IdProduit, ProdLibelle

    Ligne 17 : remplacer
    x.Langues + ', ' + z.LangueLibelle
    par
    x.Langues + ', ' + y.Prodlibelle + ' (' + z.LangueLibelle + ')'


    Avez-vous au moins utilisé le SELECT appliqué à VUE_PRODUIT ? Le quiproquo est-il toujours total ?
    (a) Faites simple, mais pas plus simple ! (A. Einstein)
    (b) Certes, E=mc², mais si on discute un peu, on peut l’avoir pour beaucoup moins cher... (G. Lacroix, « Les Euphorismes de Grégoire »)
    => La relativité n'existerait donc que relativement aux relativistes (Jean Eisenstaedt, « Einstein et la relativité générale »)

    __________________________________
    Bases de données relationnelles et normalisation : de la première à la sixième forme normale
    Modéliser les données avec MySQL Workbench
    Je ne réponds pas aux questions techniques par MP. Les forums sont là pour ça.

  12. #12
    Futur Membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 5
    Points : 6
    Points
    6
    Par défaut
    Bonsoir fsmrel,
    Je crains n'avoir pas été assez clair dès mon premier message ce qui n'a pas aidé dans la compréhension du problème.

    Le problème se situe au niveau de la création de mes classes pour gérer des produits. J'ai énoncé deux propositions dans mon précédent message et je souhaite savoir si l'une d'elles est valable (si elles ne le sont pas, quelle autre solution pourrait être envisageable).

    Les résultats de vos requêtes pourraient me permettre de créer mes objets. Cependant mon problème étant au niveau de la création de mes classes, il m'est donc impossible de créer des objets (instances de mes classes) sans classe.

    Je vous remercie de votre patience.
    Cdt,
    P.

    EDIT :

    Ma question pourrait être résumé :
    Comment traduiriez-vous le schéma de tables ci dessous en classe :
    Produit (ProdId, ProdAtt1, ProdAtt2, ProdAtta5, ..., ProdAttn)

    ProduitLangue (ProdId, LangueId, ProdLibelle, ProdAtta3, ProdAtt4)

    Langue (LangueId, LangueAtt1, ..., LangueAttn)

  13. #13
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 001
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 001
    Points : 30 905
    Points
    30 905
    Billets dans le blog
    16
    Par défaut
    Bonsoir,

    N’étant pas particulièrement un développeur (les derniers programmes que j’ai écrits étaient en assembleur...), j’aurais néanmoins tendance à confirmer votre diagramme de classes.

    A ce stade, je pense que le mieux est que vous vous tourniez vers des frameworks comme Hibernate ou Symfony et postiez dans les forums ad-hoc.

    Bon courage.
    (a) Faites simple, mais pas plus simple ! (A. Einstein)
    (b) Certes, E=mc², mais si on discute un peu, on peut l’avoir pour beaucoup moins cher... (G. Lacroix, « Les Euphorismes de Grégoire »)
    => La relativité n'existerait donc que relativement aux relativistes (Jean Eisenstaedt, « Einstein et la relativité générale »)

    __________________________________
    Bases de données relationnelles et normalisation : de la première à la sixième forme normale
    Modéliser les données avec MySQL Workbench
    Je ne réponds pas aux questions techniques par MP. Les forums sont là pour ça.

  14. #14
    Futur Membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 5
    Points : 6
    Points
    6
    Par défaut
    Je vous remercie.

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

Discussions similaires

  1. Bonnes pratiques pour une vue partagée
    Par HaloKard dans le forum MVC
    Réponses: 3
    Dernier message: 13/11/2010, 13h23
  2. Réponses: 4
    Dernier message: 02/02/2010, 23h49
  3. Bonne pratique pour une table de décision
    Par Nalfeim dans le forum Langage
    Réponses: 3
    Dernier message: 19/08/2009, 11h30
  4. Réponses: 4
    Dernier message: 01/10/2008, 08h59

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