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 :

echec on delete : a Fk constraint fails [Doctrine]


Sujet :

ORM PHP

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Février 2011
    Messages
    30
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 30
    Par défaut echec on delete : a Fk constraint fails
    Bonjour à tous

    J'utilise symfony 1.4.
    J'ai le schéma suivant :

    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
    detect_relations: true
    Parcour:
      actAs:
        Timestampable:    ~
      columns:
        sf_guard_user_id:	integer
        name:
          type:             string(255)
          notnull:          true
        seance_id:          integer
      relations:
        seance:
          foreignAlias:   parcours
      relations:
        sfGuardUser:
          foreignAlias:   	Parcours
          onDelete:   	CASCADE
     
    ParcourVideo:
      columns:
        parcour_id:
          type:           integer
        video_id:
          type:           integer
        position:
          type:           integer
        action_ident:
          type:           integer
      relations:
        parcour:
          foreignAlias:   ParcourVideos
        video:
          foreignAlias:   ParcourVideos
    je lance la requête suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $qpar = Doctrine_Query::create()
    ->delete('Parcour p')
    ->where('id = ?', $parcour_id);
    $qpar->execute();
    J'ai l'erreur suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    SQLSTATE[HY000]: General error: 1451 
    Cannot delete or update a parent row:
    a foreign key constraint fails 
    (`thesite`.`parcour_video`, 
    CONSTRAINT `parcour_video_parcour_id_parcour_id` 
    FOREIGN KEY (`parcour_id`) 
    REFERENCES `parcour` (`id`))
    Quelqu'un aurait-il la gentillesse de m'expliquer pourquoi la suppression de l'enregistrement de la table Parcour ne supprime pas automatiquement ceux de la table ParcourVideo ayant le même id (pour parcour_id).

    En effet si je supprime les enregistrements de la table ParcourVideo avant l'enregistrement de la table Parcour, via la requête suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $qparvid = Doctrine_Query::create()
    ->delete('ParcourVideo e')
    ->where('parcour_id = ?', $parcour_id);
    $qparvid->execute();
    Cela se passe très bien.
    Or j'aimerai vraiment que cela soit automatique sans être obligé de faire cette "pré-requête".

    Un grand merci par avance.

  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
    Ajouter un onDelete: cascade dans le schéma de ParcoursVideo améliorera sans doute les choses.

    Et accessoirement, parcours prend un 's', même au singulier. Une rumeur tenace affirme que Doctrine plante quand il y a des fautes d'orthographe

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Février 2011
    Messages
    30
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 30
    Par défaut
    je sais bien que parcours prend un s : c'était pour m'éviter d'avoir des parcourss

    Sinon concernant la modification, j'ai fait :
    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
    ParcourVideo:
      columns:
        parcour_id:
          type:           integer
        video_id:
          type:           integer
        position:
          type:           integer
        action_ident:
          type:           integer
      relations:
        parcour:
          foreignAlias:   ParcourVideos
          onDelete: CASCADE
        video:
          foreignAlias:   ParcourVideos
    Or j'ai à nouveau une erreur 500 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    SQLSTATE[HY000]: General error: 1451 
    Cannot delete or update a parent row: 
    a foreign key constraint fails
     (`thesite`.`parcour_video`, 
    CONSTRAINT `parcour_video_parcour_id_parcour_id` 
    FOREIGN KEY (`parcour_id`) 
    REFERENCES `parcour` (`id`))
    Avez-vous une autre idée car je sèche là ?

  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
    Pour le nom de la table, orthographiquement Herode a raison, mais doctrinement c'est richard_m qui a raison. Jamais de s sur un nom d'entité. Donc soit sans "s", soit on change le nom.

    Doctrine est sensible aux fautes d'orthographe, mais pour le cas, la faute serait d'avoir "s" sur un nom d'entité

    Une autre règle dit qu'une liaison ne doit s'écrire que sur un côté de la relation, en général le côté "n". Ta liaison est décrite deux fois ce qui ne peut que générer des problèmes.

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Février 2011
    Messages
    30
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 30
    Par défaut
    Bonjour Michel,

    Je n'ai pas compris ce que tu voulais dire : "ta liaison est décrite deux fois". Peux-tu me l'expliquer stp ?

  6. #6
    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
    Citation Envoyé par Michel Rotta Voir le message
    Doctrine est sensible aux fautes d'orthographe, mais pour le cas, la faute serait d'avoir "s" sur un nom d'entité
    Grmffffff. Anarchiste !

    @richard_m: à vue de nez, je n'ai que trois idées qui me viennent à l'esprit :
    - as-tu reconstruit ton modèle et les classes liées ?
    - as-tu reconstruit ta base de données ?
    - marginalement, as-tu vidé ton cache ?

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Février 2011
    Messages
    30
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 30
    Par défaut
    symfony doctrine:build --all --no-confirmation
    symfony cc
    symfony doctrine:data-load

    : )

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Février 2011
    Messages
    30
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 30
    Par défaut
    J'ai reformulé mon shema.yml suite à la lecture de la doc doctrine.

    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
    Video:
      actAs:
        Sluggable:
          unique: true
          fields: [name]
          canUpdate: true
      columns:
        name:
          type:           string(255)
          notnull:        true
      relations:
        Parcours:
          class: Parcour
          local: video_id
          foreign: parcour_id
          refClass: ParcourVideo
     
    Parcour:
      actAs:
        Timestampable:    ~
      columns:
        sf_guard_user_id:	integer
        name:
          type:             string(255)
          notnull:          true
        seance_id:          integer
      relations:
        seance:
          foreignAlias:     parcours
        sfGuardUser:
          foreignAlias:   	Parcours
          onDelete: 		CASCADE
        Videos:
          class: Video
          local: group_id
          foreign: video_id
          refClass: ParcourVideo
     
    ParcourVideo:
      columns:
        parcour_id:
          type:           integer
        video_id:
          type:           integer
        position:
          type:           integer
        action_ident:
          type:           integer
    Rien a changé : toujours la même erreur 500

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SQLSTATE[HY000]: General error: 1451 Cannot delete or update a parent row: a foreign key constraint fails (`besoin2sporttv`.`parcour_video`, CONSTRAINT `parcour_video_parcour_id_parcour_id` FOREIGN KEY (`parcour_id`) REFERENCES `parcour` (`id`))

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Février 2011
    Messages
    30
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 30
    Par défaut
    Pour Herode, j'ai ajouté des onDelete:Cascade pour les relations de Video et de Parcour, sans succès...

  10. #10
    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
    Oui, mais là le schéma est carrément faux : tu déclares une relation n-n dans Video + 1 relation n-n redondante dans Parcour, ce qui va provoquer des erreurs chez Doctrine. En outre, la deuxième relation fait référence à une colonne group_id que je ne vois nulle part, en fait ça ne devrait même pas "compiler".

    Essaye plutôt quelque chose comme :
    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
     
    Video:
      actAs:
        Sluggable:
          unique: true
          fields: [name]
          canUpdate: true
      columns:
        name:
          type:           string(255)
          notnull:        true
      relations:
        Parcours:
          class: Parcour
          refClass: ParcourVideo
          foreinAlias: Videos
     
    Parcour:
      actAs:
        Timestampable:    ~
      columns:
        sf_guard_user_id:	integer
        name:
          type:             string(255)
          notnull:          true
        seance_id:          integer
      relations:
        seance:
          foreignAlias:     parcours
        sfGuardUser:
          foreignAlias:   	Parcours
          onDelete: 		CASCADE
     
    ParcourVideo:
      columns:
        parcour_id:
          type: integer
          primary: true
        video_id:
          type: integer
          primary: true
        position:
          type: integer
        action_ident:
          type: integer
      relations:
        Parcour:
          onDelete: cascade
        Video:
          onDelete: cascade

  11. #11
    Membre averti
    Profil pro
    Inscrit en
    Février 2011
    Messages
    30
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 30
    Par défaut
    Herode regarde l'exemple du lien sur la doc docrine (dans mon psot précédent), c'est ce qu'ils font...

    J'essaie ta manière de faire

  12. #12
    Membre averti
    Profil pro
    Inscrit en
    Février 2011
    Messages
    30
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 30
    Par défaut
    clap clap clap, Herode !
    ça fonctionne.

    Un grand merci !

    Une dernière question :
    Tu mets une relation sur Video du type
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
      relations:
        Parcours:
          class: Parcour
          refClass: ParcourVideo
          foreinAlias: Videos
    Pourquoi ne pas mettre en sus une relation du côte de Parcour, du type
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
      relations:
        Videos:
          class: Video
          refClass: ParcourVideo
          foreinAlias: Parcours
    histoire d'être bien carré ?

  13. #13
    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
    Avec la déclaration dans Video, par exemple, Doctrine va faire le lien des deux côté grâce à la ref_class et au foreignAlias principalement. Donc le "en sus" est inutile et en programmation, ce qui est inutile a tendance a bugguer

    En fait, si tu re-déclares la relation de l'autre côté, tu vas avoir des redondances dans le code car Doctrine n'est pas assez intelligent pour les supprimer (on ne lui en veut pas, c'est moins simple qu'il n'y parait). Le risque: des méthodes en trop qui font la même chose, des erreurs sur les update/delete quand Doctrine essaye de les faire deux fois, etc.

    J'ai fait l'erreur sur mon premier projet et faute de pouvoir ré-écrire un schéma propre (et tout le code qui va avec) je m'en mords encore les doigts lors des maintenances.

  14. #14
    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
    Pourquoi ne pas mettre en sus une relation du côte de Parcour, du type
    parce que
    ta liaison serait décrite deux fois
    Une liaison entre une table A et une table B est écrite sur l'une ou (exclusif) l'autre table jamais les deux. Les paramètres à prendre en compte par l'autre côté de la branche sont précédés de "foreign".

    La liaison n-n fonctionne de la même manière trois tables, trois liaisons (dont une est un "raccourcis" entre les deux tables de base.

    Ton schéma "à ma façon".
    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
    #shema.yml
    Video:
      actAs:
        Sluggable:
          unique: true
          fields: [ name ]
          canUpdate: true
      columns:
        name:
          type:           string(255)
          notnull:        true
      relations:
        Parcours:
          class: Parcour
          refClass: ParcourVideo
          foreignAlias: Videos
     
    Parcour:
      actAs:
        Timestampable:    ~
      columns:
        sf_guard_user_id:	integer
        name:
          type:             string(255)
          notnull:          true
        seance_id:          integer
      relations:
        seance:   # Pas de relation vers parours sur la table sceance !!!
          foreignAlias:     parcours
        sfGuardUser:
          foreignAlias:   	Parcours
          local: sf_guard_user_id
          onDelete: 		CASCADE
     
    ParcourVideo:
      columns:
        parcour_id:
          type:           integer
          primary: true
        video_id:
          type:           integer
          primary: true
        position:
          type:           integer
        action_ident:
          type:           integer
      relations:
        Parcour:
          foreignAlias: ParcourVideos
        Video:
          foreignAlias: ParcourVideos
    A noter que doctrine n'apprécie pas particulièrement les liaisons n-n avec des attributs sur la liaison et qu'il est souvent préférable de les traiter comme deux liaisons n-1 et 1-n plutôt que comme une liaison n-n (qui masquera les attribut). La suppression de la relation "Parcour" sur la table "Video" est alors recommandée.

    Il restera possible de récupérer les vidéos d'un parcour par $parcour->getParcourVideos() puis, pour chaque ParcourVideo de faire un getVideo().

  15. #15
    Membre averti
    Profil pro
    Inscrit en
    Février 2011
    Messages
    30
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 30
    Par défaut
    Je vous remercie tous les deux pour l'aide et les conseils apportés.

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

Discussions similaires

  1. Réponses: 13
    Dernier message: 27/08/2015, 17h46
  2. Réponses: 2
    Dernier message: 11/07/2012, 17h52
  3. Foreign key constraint fails
    Par psgman113 dans le forum JPA
    Réponses: 2
    Dernier message: 13/03/2009, 12h37
  4. Réponses: 0
    Dernier message: 12/12/2007, 21h10
  5. [clés étrangères] a foreign key constraint fails
    Par guidav dans le forum Débuter
    Réponses: 15
    Dernier message: 09/08/2006, 23h50

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