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

ORM PHP Discussion :

Relation entre deux tables dans schema.yml sans contrainte [Doctrine]


Sujet :

ORM PHP

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2011
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2011
    Messages : 18
    Points : 10
    Points
    10
    Par défaut Relation entre deux tables dans schema.yml sans contrainte
    Bonjour,

    J'essaie de créer une simple relation entre deux tables qui sont city et region en sachant que la clé de jointure peut être vide (J'utilise des données du site Geonames et certaines villes situées sur de petites îles n'appartiennent pas à une région).

    Hors lorsque je crée la relation entre mes deux tables dans le schema.yml, Doctrine crée une clé étrangère mais aussi une contrainte entre les deux tables qui donne ceci dans le schema.sql généré :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ALTER TABLE city ADD CONSTRAINT city_admin1_code_region_admin1_code FOREIGN KEY (admin1_code) REFERENCES region(admin1_code);
    Et cela plante lorsque j'alimente ma table des villes à cause du champ admin1_code reliant mes deux tables qui peut être vide.

    J'ai toujours la possibilité de retirer la référence à la contrainte dans le schema.sql tout en le laissant dans le schema.yml mais cela n'est pas très "propre"...

    Bref, j'ai cherché, cherché mais pas trouvé une bonne solution. Quelqu'un pourrait-il m'aider ?

    Merci d'avance !

    Nino
    PS : Pour info, j'utilise Symfony 1.4.11 et donc, sauf erreur, Doctrine 1.2

  2. #2
    Membre éprouvé 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
    Points : 933
    Points
    933
    Par défaut
    Citation Envoyé par ninorotto Voir le message
    en sachant que la clé de jointure peut être vide
    L'as-tu spécifié dans ton schema.yml (notnull : false, ou rien du tout car notnull est réglé à false par défaut) ? Peut-on voir ton .yml ?

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2011
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2011
    Messages : 18
    Points : 10
    Points
    10
    Par défaut
    Bonjour Herode,

    oui, je l'ai spécifié et voici un extrait de mon schema.yml avec les 2 tables (j'ai juste enlevé les champs qui ne sont pas utiles dans l'analyse pour plus de clarté) :

    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
     
    Region:
      connection: doctrine
      tableName: region
      columns:
        id:
          type: integer(8)
          autoincrement: true
          primary: true
        iso:
          type: string(2)
          fixed: true
        admin1_code:
          type: string(8)
          fixed: true
        name:
          type: string()
      indexes:
        region_iso_index:
          fields: [iso]
        region_admin1_code_index:
          fields: [admin1_code]
     
    City:
      connection: doctrine
      tableName: city
      columns:
        id:
          type: integer(4)
          notnull: true
        name:
          type: string(100)
        latitude:
          type: 'decimal(10, 7)'
        longitude:
          type: 'decimal(10, 7)'
        admin1_code:
          type: string(8)
          notnull: false
      relations:
        Region: { local: admin1_code, foreign: admin1_code, class: Region }

    Merci !

    Nino

  4. #4
    Membre éprouvé 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
    Points : 933
    Points
    933
    Par défaut
    Hmm, je n'ai jamais essayé de déclarer une relation sur un champ qui n'est pas une clé primaire. Je ne sais pas comment Doctrine réagit là-dessus mais comme Doctrine est un peu caractériel, je me méfierais...

    Un autre détail me turlupine : le champ qui fait le lien est déclaré string(8) fixed en haut mais string(8) en base. A moins que 'fixed' soit réglé à true par défaut - à vérifier - cela peut aussi causer des soucis à Doctrine.

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2011
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2011
    Messages : 18
    Points : 10
    Points
    10
    Par défaut
    Effectivement, il y avait une différence entre les deux champs car par défaut, fixed est à faux. J'ai donc supprimé le fixed=true pour faire un test et cela me crée la même contrainte.

    J'ai aussi essayé de déclarer un ON UPDATE NO ACTION et un ON DELETE NO ACTION dans la relation pour qu'il crée la clé étrangère sans la contrainte mais rien à faire...

    En sachant que mes tables city et region n'évolueront pas dans le temps, elles sont utilisées en tant que tables de références et si je ne trouve pas de solution, soit :
    - je laisse la relation dans le schema.yml, mais j'enlève dans le schema.sql la contrainte. Ma relation existera donc dans le modèle et sera utilisable.
    - je ne crée pas de relations dans mon schema.yml, ce qui signifie que je ne pourrai pas utiliser la relation dans mes requêtes en DQL, ce qui semble moins pratique (à priori...).

    Si vous avez des conseils, je suis preneur, car je développe pour le plaisir et cela n'en est plus un quand on rencontre plusieurs problèmes de ce type (j'en ai d'autres en parallèle).

    D'ailleurs, l'utilisation d'un framework était censé me faire gagner du temps, c'était le cas au tout début mais je pense qu'au final, ce n'est plus le cas. Et pourtant, je lis le maximum de ressources sur le web pour essayer de faire au mieux.

    Bref...

    Nino

  6. #6
    Membre éprouvé 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
    Points : 933
    Points
    933
    Par défaut
    Mon conseil serait d'utiliser la clé primaire id comme clé étrangère region_id. C'est plus orthodoxe et dans cette configuration, avec notnull = false, ça devrait marcher.

    Quand à gagner du temps avec des frameworks, ça se discute. Avec symfony, le problème que j'ai régulièrement est que sur les opérations simples et standard, une fois passée la phase d'apprentissage (longue et douloureuse), ça fait effectivement gagner du temps - mais il y a d'autres avantages non négligeables : code normalisé, propre, maintenance facilitée. Par contre, quand je tombe sur un os, ça peut très vite dériver gravement et me prendre plusieurs jours pour régler proprement une question que j'aurais torchée en une demi-journée hors framework.

    Il faut aussi voir quels sont les besoins réels. Pour une grosse application en intranet/extranet, symfony vaut sans doute le coup. Pour des projets persos ou plus modestes, il y a des frameworks bien plus légers et très satisfaisants (j'ai fait quelques essais comparatifs sur Yii récemment, par exemple, c'est intéressant). A vue de nez, je dirai que symfony demande au minimum un à deux ans à temps plein pour être correctement maitrisé. C'est un investissement à long terme - et un combat de tous les instants.

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2011
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2011
    Messages : 18
    Points : 10
    Points
    10
    Par défaut
    Salut Herode !

    J'ai essayé ce que tu m'as conseillé en modifiant mon schema.yml que voici (j'ai enlevé les champs inutiles) :

    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
     
    Region:
      connection: doctrine
      tableName: region
      columns:
        id:
          type: integer(8)
          autoincrement: true
          primary: true
        name:
          type: string()
     
    City:
      connection: doctrine
      tableName: city
      columns:
        id:
          type: integer(4)
          notnull: true
        name:
          type: string(100)
        region_id:
          type: integer(8)
          notnull: false
      relations:
        region: { local: region_id, foreign: id, class: Region }
    Et..... cela ne fonctionne pas, j'ai toujours la contrainte qui est créée

    j'ai bien indiqué le même type de données integer(8) et le notnull à false.

    En dehors de ce problème, quels sont mes besoins ?
    créer une appli web de façon structurée avec les bonnes pratiques, d'où l'utilisation d'un framework.
    j'ai choisi Symfony car j'avais déjà fait du php et que j'ai lu de très bons commentaires sur ce framework.
    Mon objectif, si j'arrive à créer cette première appli est d'en créer d'autres. Ce n'est donc pas du one shot. J'aimerais donc pouvoir capitaliser sur cette expérience, si j'en sors pas blasé
    C'est un projet à titre personnel car je ne suis pas développeur (ancien admin système et maintenant dans la sécu informatique).
    J'entends également beaucoup parler de Django mais je n'ai jamais fait de Python et après 2 mois de Symfony, ce serait dommage de changer de framework et langage.
    Le point positif, c'est que le tutoriel Jobeet de Symfony m'a éclairé sur les bonnes pratiques et que ce temps passé à le lire ainsi que les forums est une expérience qui peut être réutilisé pour tout projet web, quel que soit le langage.

    Voilà, j'ai tout dit, je ne sais pas si cela se fait de s'étendre sur ses histoires persos sur un fil de discussion technique d'un problème. Je fais mes débuts sur les forums...

    En tout cas, et même si cela ne fonctionne pas, merci pour ton aide et tes conseils

    Nino

  8. #8
    Membre éprouvé 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
    Points : 933
    Points
    933
    Par défaut
    Ha bah, un peu de hors sujet de temps en temps, ça détend

    Mais pour en revenir à la question, il va falloir vérifier un peu tout ça.

    1 - les détails secondaires d'abord : ton schema.yml n'est pas optimisé pour Doctrine. Regarde l'API de Doctrine (http://www.doctrine-project.org/proj...l-schema-files) pour les détails. L'idée générale est : quand on peut utiliser les valeurs par défaut et les conventions de Doctrine, on se simplifie la tâche.

    Ici -> table City : id -> integer(4) contre integer(8) dans l'autre table, pas d'autoincrément. A moins d'avoir de très fortes raisons de se compliquer la vie, utiliser un type unique et l'autoincrément pour les ids est préférable. En outre, quand on ne déclare pas de clé primaire, Doctrine la construit implicitement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    id: { type:integer, autoincrement: true, primary: true }
    De même pour les relations : si ta relation ointe sur la table MaTable, Doctrine va supposer que la colonne concernée s'appelle ma_table_id.

    Schema nettoyé :
    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
    Region:
      columns:
        name:
          type: string()
     
    City:
      columns:
        name:
          type: string(100)
        region_id:
          type: integer
          notnull: false
      relations:
        Region: 
          foreignAlias: Cities
    On pourrait ajouter facilement quelques colonnes utiles comme les created_at et updated_at (grâce auix behaviours) mais c'est une autre histoire.

    Cela dit, même si je reprends ton schema tel quel...

    2 - ... et que je fais doctrine:build --all (+ nettoyage du cache), j'obtiens une base de données correcte et une requête comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    insert into city (name) values('test');
    fonctionne parfaitement (avec region_id = NULL par défaut).

    Donc, si le problème persiste, faire le ménage :
    - suppression manuelle du fichier data/sql/schema.sql
    - php symfony doctrine:clean-model-files
    - php symfony cc
    - php symfony build --all (ou build --all --and-load si tu as des fixtures)

    Si ça bloque toujours, indique-nous exactement quelle fixture / quel écran / quelle opération sont concernés, on y verra plus clair.

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2011
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2011
    Messages : 18
    Points : 10
    Points
    10
    Par défaut
    Bonjour Herode,

    tout d'abord, merci pour cette nouvelle réponse et les tests effectués de ton côté. J'ai fait la même manipulation que toi et cela a fonctionné pour l'exemple donné.

    Je remarque que la contrainte (ADD CONSTRAINT) est bien présente dans le schema.sql mais que cela ne pose finalement pas de problème lors de l'insertion d'une donnée NULL dans le champ de la clé étrangère.

    Initialement, je pensais que c'était le problème car lorsque je faisais un import d'un fichier csv dans la table, j'avais une erreur liée à la clé étrangère. Pour rappel, j'utilise des fichiers texte pour les villes, régions et pays issus du site Geonames.org.

    C'est pour cette raison d'ailleurs que mon schema n'exploite pas les atouts de Doctrine. J'hérite des fichiers textes Geonames et des relations qui y sont intégrées. L'id de la table ville n'est pas séquentiel et c'est normal. Mon code région n'est pas un id numérique mais un code ISO à 2 chiffres.

    Bref, pour utiliser proprement les données, il faudrait que je remodélise ces tables et leurs liaisons. Cela n'est probablement pas si compliqué que ça mais c'est du travail. Actuellement, ce que j'ai en place fonctionne, reste à voir si je repars à zéro sur ces tables ou pas. Etant donné que je suis au début de mon site, je peux le faire, c'est une histoire de choix...

    Dans tous les cas, tout ces problèmes et tes conseils m'auront appris des choses sur Doctrine

    Un grand merci pour ton aide !

    Nino

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

Discussions similaires

  1. [DEBUTANT]Problème de relation entre deux tables
    Par Yomane dans le forum Schéma
    Réponses: 2
    Dernier message: 20/10/2006, 01h30
  2. relation entre deux tables
    Par tojiji dans le forum Access
    Réponses: 6
    Dernier message: 04/07/2006, 14h44
  3. Problème de relation entre deux tables + autre chose
    Par Goth_sensei dans le forum Langage SQL
    Réponses: 7
    Dernier message: 30/03/2006, 20h49
  4. [XSD] Relation entre deux tables
    Par fd59 dans le forum Valider
    Réponses: 2
    Dernier message: 09/09/2005, 23h33
  5. Relation entre deux tables
    Par manel007 dans le forum Langage SQL
    Réponses: 5
    Dernier message: 04/03/2005, 16h54

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