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 :

Relations many to many dans schema.yml


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
    Septembre 2009
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 32
    Par défaut Relations many to many dans schema.yml
    Bonjour à tous,

    je développe un projet perso de gestion de catalogue d'oeuvres d'art et je bute sur un problème assez énervant.

    Dans ce projet, je souhaite inclure une gestion des métadonnées. En clair, un utilisateur doit pouvoir définir des métadonnées sur une oeuvre ou un artiste.

    Niveau base de données cela se traduit par une relation many to many de la manière suivante :

    1 artiste peut avoir N métadonnées
    1 même métadonnée peut etre appliquée sur plusieurs artistes

    idem avec les oeuvres:

    1 oeuvre peut avoir N métadonnées
    1 même métadonnée peut etre appliquée sur plusieurs oeuvres

    Jusque là pas de problème, j'y viens donc

    Je ne sais pas comment définir ça en symfony.
    Le message d'erreur que j'ai est le suivant lorsque je crée le modèle et que j'insère les fixtures :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
      SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`airexpo`.`oeuvre`, CONSTRAINT `oeuvre_artiste_id_artiste_id` FOREIGN KEY (`artiste_id`) REFERENCES `artiste` (`id`))
    Il semble que la relation many to many que j'ai définie ne le soit pas correctement.

    La table de métadonnées est "metadata"
    La table des artistes est "artiste"
    La table des oeuvres est "oeuvre"
    La table de relation entre métadonnées et artistes ou oeuvres est "defined_metadata"

    Voici la définition de la classe DefinedMetadata dans le fichier schema.yml :

    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
     
    DefinedMetadata:
        actAs: 
          Timestampable: ~
        columns:
            metadata_id: 
              type: integer
            oeuvre_id:
              type: integer
            artiste_id:
              type: integer
        relations:
          Artiste:
            class: Artiste
            local: artiste_id
            foreign: id
            refClass: DefinedMetadata
          Oeuvre:
            class: Oeuvre
            local: oeuvre_id
            foreign: id
            refClass: DefinedMetadata
    J'ai inclus le fichier schema.yml pour plus de précisions.

    Si quelqu'un a une idée...
    Fichiers attachés Fichiers attachés

  2. #2
    Membre émérite Avatar de Herode
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2005
    Messages
    825
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2005
    Messages : 825
    Par défaut
    Hmmm, le message d'erreur ne fait pas référence à ta table de liaison DefinedMetadata mais à la table Oeuvre et à son lien vers Artiste. Cela dit, la définition pour la table de liaison me semble fautive en effet. L'entrée relations|RefClass permet à Doctrine de savoir quelle est la table de liaison : celle qui est gouvernée par la classe RefClass. Tu l'utilises donc sur les deux tables à lier mais pas sur la table de liaison elle-même.

    Cela donnerait plutôt :

    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
    DefinedMetadata:
        actAs: 
          Timestampable: ~
        columns:
            metadata_id: 
              type: integer
            oeuvre_id:
              type: integer
            artiste_id:
              type: integer
        relations:
          Artiste:
            local: artiste_id
            foreign: id
          Oeuvre:
            local: oeuvre_id
            foreign: id
    Par contre, je n'ai jamais essayé de faire une table de liaison entre 3 tables avec clés facultatives + références croisées Oeuvre/Artiste depuis la table Oeuvre...
    Et je n'ai pas testé ça avec fixtures. Donc je ne garantis pas que le résultat soit celui attendu.

  3. #3
    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
    Deux choses :

    Peux tu mettre ton shema.yml complet, le vérifier partiellement n'est pas possible vu que les relations impactent deux tables (voir plus dans le cas de relations n-n).

    Je t'invite à jeter un oeil sur le plugin sfDoctrineActAsTaggablePlugin il pourrait répondre à ton besoin vu que ce que tu souhaites est d'appliquer des TAG sur un artiste.

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 32
    Par défaut
    @herode
    Merci de ta réponse et de ton aide, j'essaierai ce soir, je n'ai pas la possibilité de tester maintenant

    @mimi68
    J'ai attaché mon fichier schema.yml à ce topic, c'est le fichier txt que tu vois. Il faut juste le renommer de txt à yml (je n'ai pas réussi à poster le fichier directement avec l'extension .yml)

    Je regarderai ce plugin également en tout cas

  5. #5
    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
    Ton shema.yml ne peut pas fonctionner, de plus, il n'est pas conforme à ce que tu dis dans ton premier post.

    Le message d'erreur vient de la définition du lien dans la table Artiste d'un lien vers Metadata.

    Mais le vrais problème vient de la table DefineMetadata qui défini une relation n-n-n ou un truc dans le style. De ce qui est plus ou moins défini, elle permet d'attribuer un metadata à un artiste ou un metadata à une œuvre ou une œuvre à un artiste ou un metadata et une œuvre et un artiste ensemble... Sans compter l'utilisation hors propos de refClass qui ne peut être défini sur la class de référence elle même, celle-ci ne pouvant être envisager que dans le cadre d'une liaison n-n sans arguments... Donc, il faudra revoir cette table, à mon avis elle devrait être séparée en trois, liaison artiste <-> œuvre, une pour la liaison artiste <-> metadata et une troisième pour œuvre <-> metadata

    Et ce demander si les metadata doivent être stockées dans la même table pour les artistes et les œuvres.

    Autres choses, tu utilises une table users (la seul au pluriel)(il est recommandé, dans symfony, pour les objets du modèle, de ne jamais avoir de "s" en fin de nom), tu devrais jeter un œil sur le plugin sfDoctrineGuardPlugin qui gère les utilisateurs, les droits, les groupes, le login et le logout. Et un deuxième œil sur le plugin sfForkedDoctrineApplyPlugin qui est un complément a sfDoctrineGuardPlugin et permet de gérer la création des users, vérification des email, modification et récupération des password par email, l'ajout de données complémentaires sur l'utilisateur.

    Bon, avec le précédent on va se retrouver avec trois yeux a gérer ce qui pourrait poser problèmes


    Si tu peux clarifier les liaisons entre les tables œuvre, artiste et metadata, je peux te faire une ébauche de schéma qui tienne la route.

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 32
    Par défaut
    ok, donc je voudrais que mon schéma répondre à ces contraintes :

    - les métadonnées ne sont applicables que sur un artiste ou sur une oeuvre
    - un artiste ou une oeuvre peut avoir un nombre illimité de métadonnées
    - on peut affecter une même métadonnée à plusieurs oeuvres ou artistes
    - on ne supprime une métadonnée si et seulement si elle n'est rattachée à aucun objet

    Par ailleurs, la structure de la base doit permettre de faire des recherches par métadonnées et de ramener indifféremment des artistes ou des oeuvres sur lesquels auront été appliquée la métadonnée

  7. #7
    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
    On approche de la solution.

    Quid de la table commentaire ? Un commentaire est fait par un user et corresponds à une oeuvre ou à un artiste ? Ou alors à la combinaison oeuvre-artiste, ce qui n'a pas d'intérêt puisque qu'une oeuvre est déjà liée à un artiste unique.

    A moins que le commentaire sois soit pour une oeuvre, soit pour un artiste, dans ce cas, je pense qu'il serait préférable de modifier légèrement la structure.


    Autre chose, quid des oeuvres réalisées par plusieurs artistes en commun ?


    On garde une table user ou on passe sur sfGuard ? (préférable)

    Ceci devrait être les dernières questions !


    ---- Edit

    Autres questions

    Je me demande s'il ne serait pas plus intéressant et performant de remplacer les descriptions en string(9999) par ces clob.

    Les images sont limitées à une par artistes et une par oeuvre. Rien ne permet depuis le fichier image de savoir si elle vient d'un artiste ou d'une oeuvre. Une structure avec deux tables de liaisons n-n permettrait d'avoir plusieurs images d'un artistes et plusieurs images d'une oeuvre.

    Une autre solution serait de "donner leur indépendance" aux images en enrichissant un peu le fichier image une description, un copyright, une origine, une version en petit,... et éventuellement initier la liaison vers artiste et/ou oeuvres depuis l'image. Donc possibilité d'avoir plusieurs images par artistes et/ou œuvres.

    On peut aussi envisager de ne pas les liées mais de les intégrer par liens, dans les articles (avec un éditeur riche). Un peu plus lourd à gérer, mais plus intéressant graphiquement, peut-être.

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 32
    Par défaut
    Bonjour mimi,

    Désolé de ne pas avoir répondu avant, je n'ai pas pu trouver le temps.

    Un commentaire est fait par un user et corresponds à une oeuvre ou à un
    artiste ?
    Oui, exactement. Un commentaire est lié à une oeuvre, artiste ou image.
    Mon idée était d'ajouter une table commentaire générique afin de ne pas avoir à manipuler plusieurs objets commentaires dans le code PHP (par exemple commentaire_artiste, commentaire_oeuvre, etc...). Tu crois que c'est faisable ?

    Je n'ai pas d'impératif particulier au niveau de la structure de la base, je veux juste aller au plus pratique. Pour le code PHP c'est pareil, je voudrais pouvoir gérer un seul objet commentaire pour chaque type d'objet (image, oeuvre, artiste, etc...), et ne pas "figer" le modèle afin de pouvoir l'étendre par la suite (d'ou l'idée de la table générique)

    Autre chose, quid des oeuvres réalisées par plusieurs artistes en commun ?
    Oui, ce n'est pas possible en l'état, mais idéalement ce serait bien de pouvoir l'intégrer

    On garde une table user ou on passe sur sfGuard ? (préférable)
    Passons sur sfGuard si c'est préférable

    Une structure avec deux tables de liaisons n-n permettrait d'avoir plusieurs images d'un artistes et plusieurs images d'une oeuvre.
    Ben, actuellement on peut déjà lier plusieurs images à un artiste ou une oeuvre. La relation est de type many et la fk est hébergée sur les tables artiste et oeuvre.

    Une autre solution serait de "donner leur indépendance" aux images en enrichissant un peu le fichier image une description, un copyright, une origine, une version en petit,... et éventuellement initier la liaison vers artiste et/ou oeuvres depuis l'image. Donc possibilité d'avoir plusieurs images par artistes et/ou œuvres.
    C'est pas mal mais les utilisateurs finaux ne veulent pas entrer tant de détails. La photo avec une légende et une métadonnée leur suffit. Ca allège l'interface.

    On peut aussi envisager de ne pas les liées mais de les intégrer par liens, dans les articles (avec un éditeur riche). Un peu plus lourd à gérer, mais plus intéressant graphiquement, peut-être.
    Ca peut etre bien aussi. Je ne sais pas ce qui est le plus ergonomique. En tout cas l'éditeur riche, je l'intégrerai c'est sur (histoire de pouvoir au moins choisir une couleur de texte)

    Voilà la vue d'ensemble de mon projet : )

  9. #9
    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
    Désolé, mais j'ai été un peu long aussi.

    C'est un des schémas les plus tordu que j'ai eu l'occasion de mettre en œuvre, et plus c'est tordu, plus j'aime...

    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
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
     
    Image:
      columns:
        connect_id: intetger
        url: string(1024)
        legende: string(255)
     
    ImageArtiste:
      inheritance:
        extends: Image
        type: column_aggregation
        keyField: type
        keyValue: 1
      relations:
        Artiste:
          local: connect_id
          foreign: id
          foreignAlias: Images
     
    ImageOeuvre:
      inheritance:
        extends: Image
        type: column_aggregation
        keyField: type
        keyValue: 2
      relations:
        Artiste:
          local: connect_id
          foreign: id
          foreignAlias: Images
     
     
    Artiste:
      actAs: 
        Timestampable: ~
      columns:
        nom: string(255)
        description: clob
        image_id: integer
      relations:
        Metadatas:
          class: Metadata
          foreignAlias: Artistes
          refClass: MetadataArtiste
     
    Oeuvre:
        actAs:
            Timestampable: ~
        columns:
            type_oeuvre_id: integer
            artiste_id: integer 
            description: string(9999)
            nom: string(255)
            image_id: integer
        relations:
            Type:
                local: type_oeuvre_id
                foreign: id
                foreignAlias: Oeuvres
            Artiste:
                local: artiste_id
                foreign: id
                foreignAlias: Oeuvres
            Metadatas:
                class: Metadata
                foreignAlias: Oeuvres
                refClass: MetadataOeuvre
     
    Commentaire:
        actAs:
          Timestampable: ~
        columns:
            text: clob
            connect_id: integer
     
    CommentaireOeuvre:
      inheritance:
        extends: Commentaire
        type: column_aggregation
        keyField: type
        keyValue: 1
      relations:
        Oeuvre:
          local: connect_id
          foreign: id
          foreignAlias: Commentaires
     
    CommentaireArtiste:
      inheritance:
        extends: Commentaire
        type: column_aggregation
        keyField: type
        keyValue: 2
      relations:
        Artiste:
          local: connect_id
          foreign: id
          foreignAlias: Commentaires
     
    CommentaireImage:
      inheritance:
        extends: Commentaire
        type: column_aggregation
        keyField: type
        keyValue: 3
      relations:
        Image:
          local: connect_id
          foreign: id
          foreignAlias: Commentaires
     
    TypeOeuvre:
        columns: 
            nom: string(255)
     
    Users:
        actAs: 
          Timestampable: ~
        columns:
            username: string(255)
            password: string(255)
            last_seen: timestamp
     
    Metadata:
      columns:
        tag: string(20)
      indexes:
        fields:
          tag:
            sorting: ASC
     
    MetadataArtiste:
      columns:
        metadata_id:
          type: integer
          primary: true
        artiste_id:
          type: integer
          primary: true
      relations:
        metadata:
          local: metadata_id
          foreign: id
          foreignAlias: MetadataArtistes
        artiste:
          local: artiste_id
          foreign: id
          foreignAlias: MetadataArtistes
     
    MetadataOeuvre:
      columns:
        metadata_id:
          type: integer
          primary: true
        oeuvre_id:
          type: integer
          primary: true
      relations:
        metadata:
          local: metadata_id
          foreign: id
          foreignAlias: MetadataArtistes
        oeuvre:
          local: oeuvre_id
          foreign: id
          foreignAlias: MetadataArtistes
    Quelques explications.

    Pour ce qui est des liaisons n-n entre metadone et artiste ainsi que metadone et oeuvre, il y a une table de liaison, avec deux clef primaires qui permettent de créer ces liaisons.
    Pour obtenir d'un artiste $artiste les métadonnées qui lui sont rattachées, il faut utiliser $artiste->getMetadones() et pour récupérer d'une métadonnée les artistes on va faire un $metadone->getArtiste().

    Ca c'est la partie facile.

    Reste le truc un peu génial de doctrine, je vais traiter de la table image, pour la table message, c'est le même principe. J'ai utilisé la notion d'héritage de table par agrégation de colonne. L'idée est d'avoir une table image avec cinq champs (id autogénéré, connect_id pour la liaison avec les autres tables, url, legende et type créé automatiquement pour différencier les héritages entres eux. C'est un peu comme si tu avais deux tables images, mais une seul base.

    Au niveau des objects, le fonctionnement est un peu particulier, à la base, il y a un objet BaseImage qui est parent d'Image. Ceci est le fonctionnement normal des objets. Par contre, l'objet BaseImageArtiste hérite, lui, de Image. Donc, toutes modifications de image (on ne touche jamais aux fichiers bases) va impacter les fichiers hérités ImageArtiste et ImageOeuvre. Il en va de même pour le formulaire. Il est ainsi possible d'utiliser le formulaire ImageOeuvre, comme formulaire de saisie, ou le formulaire ImageArtiste, ils sont identique (sauf si tu juges utile d'y apporter des modification).

    Dans les liaisons qui me semble manquer, je me suis mal exprimer, c'est plutôt l'idée qu'une oeuvre pourrait être la réalisation de plusieurs artistes différents. Il serait donc envisageable d'avoir une liaison n-n entre oeuvre et artiste.


    Je n'ai pas touché à la table user, utiliser sfGuard est relativement simple et les liaisons sont très limitées, donc, on en reparlera dans un deuxième temps.

    Je n'ai testé que partiellement, je te laisse le soins d'aller plus loin et de vérifier que ceci colle à tes besoins.

  10. #10
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 32
    Par défaut
    Bonjour mimi,

    Merci beaucoup ! Je teste ce week end des que possible et te tiens informé !

  11. #11
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 32
    Par défaut
    bonsoir mimi,

    je viens de tester le schéma que tu m'as donné et j'ai l'erreur suivante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    No columns given for index fields_idx
    également j'ai eu plusieurs notice lors du build du schéma, je les ai incluses dans le fichier joint à mon post

    aurais tu une idée de quoi il pourrait retourner ?
    Fichiers attachés Fichiers attachés

Discussions similaires

  1. Réponses: 3
    Dernier message: 31/01/2012, 19h04
  2. [Doctrine] Relation entre deux tables dans schema.yml sans contrainte
    Par ninorotto dans le forum ORM
    Réponses: 8
    Dernier message: 24/08/2011, 10h26
  3. [1.x] Relation Many to Many et colonnes dans la table association
    Par PeytaWodka dans le forum Symfony
    Réponses: 11
    Dernier message: 16/05/2011, 10h26
  4. [1.x] clés primaire dans schema.yml
    Par kamdad dans le forum Symfony
    Réponses: 13
    Dernier message: 24/04/2009, 15h58
  5. [1.x] index=unique dans schema.yml
    Par kamdad dans le forum Symfony
    Réponses: 4
    Dernier message: 23/04/2009, 17h55

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