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 :

Problème de requète entre symfony et doctrine lors du save d'un formulaire embarqué [1.x]


Sujet :

Symfony PHP

  1. #1
    Membre averti
    Homme Profil pro
    Webmaster
    Inscrit en
    Août 2006
    Messages
    55
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Webmaster
    Secteur : Santé

    Informations forums :
    Inscription : Août 2006
    Messages : 55
    Par défaut Problème de requète entre symfony et doctrine lors du save d'un formulaire embarqué
    Bonjour,

    J'ai un formulaire qui rassemble une classe doctrine et ses relations (one-to-many). Au moment du save(), je me retrouve avec un :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '1' for key 'PRIMARY'
    qui me renvoit sur (niveau logs) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    execute : INSERT INTO copisim_etudiant (anonyme, annee, id, fac, email_tmp, updated_at) VALUES (?, ?, ?, ?, ?, ?) - (0, TCEM1, 1, 13, , 2011-01-06)
    L'erreur est normale, vu qu'il veut insérer l'utilisateur courant qui édite son formulaire. La question, à laquelle je n'arrive pas à répondre, c'est : pourquoi Symfony envoie-t-il un INSERT au lieu d'un UPDATE à Doctrine ?

    J'ai vérifié avec WebDevelopper, les champs du formulaire sont correctement présents et remplis (notamment l'Id de l'utilisateur). J'ai dû rater un truc mais là je sèche depuis un moment...

    Le schéma :
    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
    CopisimEtudiant:
      actAs:
        Timestampable: 
          created: { disabled: true }
          updated: { format: Y-m-d }
      columns:
        nom: { type: string(50), notnull: true }
        prenom: { type: string(50), notnull: true }
        fac: { type: integer, notnull: true }
        naissance: { type: date }
        email: { type: string(100), notnull: false }
        email_tmp: { type: string(100), notnull: false }
        anonyme: { type: boolean, notnull: true, default: 0 }
        annee: { type: enum, values: ['DCEM4', 'DCEM4 doublant', 'TCEM1'], default: 'DCEM4' }
        classement: { type: integer, notnull: true }
      relations:
        CopisimFac: { local: fac, foreign: id }
     
    CopisimChoix:
      actAs:
        Timestampable: ~
      columns:
        etudiant: { type: integer, notnull: true }
        poste: { type: integer, notnull: true }
        ordre: { type: integer(2), notnull: true }
      relations:
        CopisimEtudiant: { local: etudiant, foreign: classement }
        CopisimPoste: { local: poste, foreign: id }
     
    [...]
    La classe de formulaire (pas la plus clean du monde mais devrait quand même marcher) :
    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
    class CopisimEtudiantChoixForm extends BaseCopisimEtudiantForm
    {
      public function configure()
      {
        unset($this['nom'], $this['prenom'], $this['naissance'], $this['email'], $this['adresse'], $this['classement'], $this['created_at'], $this['updated_at']);
     
    		$this->widgetSchema['fac'] = new sfWidgetFormInputHidden();
    		$this->widgetSchema['anonyme'] = new sfWidgetFormInputHidden();
    		$this->widgetSchema['email_tmp'] = new sfWidgetFormInputHidden();
    		$this->widgetSchema['annee'] = new sfWidgetFormInputHidden();
     
    		$this->embedRelation('CopisimChoix');
     
    		$newChoix = new CopisimChoixForm();
    		$newChoix->setDefault('etudiant', $this->object->id);
    		$this->embedForm('ajouter', $newChoix);
      }
     
      protected function doBind(array $values)
      {
      	if ('' === trim($values['ajouter']['poste']) && '' === trim($values['ajouter']['ordre']))
      	{
      		unset($values['ajouter'], $this['ajouter']);
      	}
     
      	parent::doBind($values);
      }
    }
    La classe actions :
    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
    [...]
     
    public function executeEditchoix(sfWebRequest $request)
      {
        $this->user = $this->getUser()->getUsername();
        $this->forward404Unless($copisim_etudiant = Doctrine::getTable('CopisimEtudiant')->find(array('id' => $this->getUser()->getUsername())), sprintf('Utilisateur inconnu : (%s).', $this->getUser()->getUsername()));
        $this->form = new CopisimEtudiantChoixForm($copisim_etudiant);
      }
     
      public function executeUpdatechoix(sfWebRequest $request)
      {
        $this->user = $this->getUser()->getUsername();
        $this->forward404Unless($request->isMethod(sfRequest::POST));
        $this->form = new CopisimEtudiantChoixForm();
     
        $this->form->bind($request->getParameter($this->form->getName()), $request->getFiles($this->form->getName()));
        if($this->form->isValid())
        {
          $this->form->save();
          $this->redirect('etudiant/editchoix');
        }
        $this->setTemplate('editchoix');
      }
     
    [...]
    Je n'ai pas mis le reste, vu que ça n'apporte pas grand chose au problème... Concrètement, c'est ma classe de formulaire que je serais le plus enclin à mettre en doute, mais en pratique je ne comprends pas pour autant l'erreur entre INSERT et UPDATE. Si quelqu'un a une idée, merci d'avance !

  2. #2
    Membre éprouvé

    Homme Profil pro
    Software Engineer
    Inscrit en
    Août 2004
    Messages
    173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Software Engineer
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Août 2004
    Messages : 173
    Par défaut
    Essai d'utiliser $this->useFields(array()); au lieu des unset();

    tu met dedans la liste des champs utilisés au lieu de lister ceux que tu ne veux pas.
    Ca sent la clé pas unset la où il faut.

    Cette méthode évite généralement les problèmes de clé étrangère. Il faut la mettre dans la classe form parent et celle de l'embedForm également.

  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
    Je vois que tu as un embed normal et un nouveau form qui est aussi en embed.

    Personnellement, je ne procèderais pas ainsi. Je pense que c'est là l'origine du problème. Essaye de faire deux form dans ta page, le deuxième pour l'ajout et indépendant du premier au niveau html.

  4. #4
    Membre averti
    Homme Profil pro
    Webmaster
    Inscrit en
    Août 2006
    Messages
    55
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Webmaster
    Secteur : Santé

    Informations forums :
    Inscription : Août 2006
    Messages : 55
    Par défaut
    Alors, j'ai testé avec $this->useFields(array()); en virant le unset, ça n'a rien changé.

    J'ai également testé en introduisant une donnée en relation directement dans la base, et là j'ai eu message d'erreur au niveau de la validation qui disait que le champ inclu par embedRelation(); n'avait rien à faire dans le formulaire...

    Chaque chose en son temps, et j'ai donc refait un test en virant le useFields(); et le unset();, après tout, c'est une édition, je ne devrais pas faire de bêtises. Là, apparaìt une chose intéressante : le champ CopisimEtudiant.classement apparaît comme un menu déroulant vide. Il faut savoir qu'il y a une relation One-to-one avec la table d'utilisateurs de sfDoctrineGuardPlugin... mais pour laquelle, je ne trouve pas de déclaration (c'est dans ces moment-là qu'on se dit qu'on a dû faire les choses salement : c'est un projet resté en veille faute de temps à y consacrer)... Ceci dit, ça n'explique pas pourquoi il est nul alors que la table mySQL ne l'est pas pour ce champ. Et par ailleurs, une autre classe de formulaire CopisimEtudiantForm fonctionne correctement sur la même table.

    Pour ce qui est du embedRelation() associé à un embedForm() pour la création d'un nouvel enregistrement, c'est un point sur lequel j'avais trouvé quelques exemples sur le net, et ça ne semblait pas poser problème.

    Edit : pour statuer là-dessus, j'ai commenté tour à tour, puis simultanément, les deux embed dans la classe de formulaire, avec toujours le même bug. Du coup, je me concentrerais plutôt sur les différence entre les classes CopisimEtudiantForm et CopisimEtudiantChoixForm...

    CopisimEtudiantForm :
    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
    class CopisimEtudiantForm extends BaseCopisimEtudiantForm
    {
      public function configure()
      {
        $this->embedForm('MdP', new copisimUserPasswordForm(sfContext::getInstance()->getUser()->getGuardUser()));
     
        unset($this['nom'], $this['prenom'], $this['fac'], $this['created_at'], $this['updated_at'], $this['classement']);
     
        $this->validatorSchema['email_tmp'] = new sfValidatorAnd(array(
          $this->validatorSchema['email_tmp'],
          new sfValidatorEmail(),
        ));
     
        $this->widgetSchema['email'] = new sfWidgetFormInputHidden();
        $this->widgetSchema->setLabel('email_tmp', 'Email');
      }
    }
    Et je n'en vois aucun qui justifie le changement de comportement de Symfony... Au niveau des actions, c'est le même appel en changeant le nom de la classe.

  5. #5
    Membre averti
    Homme Profil pro
    Webmaster
    Inscrit en
    Août 2006
    Messages
    55
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Webmaster
    Secteur : Santé

    Informations forums :
    Inscription : Août 2006
    Messages : 55
    Par défaut
    Bon je suis honteux de vous avoir dérangés avec ça...

    L'erreur était basique, l'erreur était logique : lors de la mise à jour de ma fonction Uptdatechoix($sfWebRequest), j'avais fait une erreur dans la requête Doctrine... Forcément, Symfony ne trouvait pas l'objet, forcément il voulait en insérer un nouveau... Bref.

    Merci de vos réponses qui m'ont permis de me remettre sur les rails !

    Encore quelques bugs (notamment le doSave) mais je devrais pouvoir m'en sortir. Encore merci !

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

Discussions similaires

  1. [Oracle] Requêtes entre Oracle et php
    Par mido393 dans le forum PHP & Base de données
    Réponses: 2
    Dernier message: 01/01/2015, 20h15
  2. problème de requète lors d'un tri par combobox
    Par inforlab dans le forum Windows Forms
    Réponses: 1
    Dernier message: 02/12/2008, 22h52
  3. [BO 5.1.9] Problème de Lien entre 2 requêtes
    Par jbbabb dans le forum Débuter
    Réponses: 5
    Dernier message: 21/11/2007, 10h47
  4. Réponses: 1
    Dernier message: 10/10/2007, 17h08
  5. ACCESS 97, requête union, problème de liaison entre 2 requêtes
    Par AGR26 dans le forum Requêtes et SQL.
    Réponses: 3
    Dernier message: 10/09/2007, 18h00

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