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 :

[Symfony2] update des champs dans mon entité avec editAddAction() de mon controller ne fonctionne pas


Sujet :

Symfony PHP

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2014
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Décembre 2014
    Messages : 24
    Points : 8
    Points
    8
    Par défaut [Symfony2] update des champs dans mon entité avec editAddAction() de mon controller ne fonctionne pas
    Bonjour à tous,

    voilà en gros mon soucis: j'ai une page d'index qui m'affiche dans un tableau tous les champs d'une entité dans ma base. Dans ce tableau, ce trouve un bouton edit qui me récupère le champ spécifique (ici le nom), pour ensuite le modifier dans un formulaire. Une fois le formulaire remplit, je le valide et normalement le nom doit être modifié.

    Voici le code de cette vue (template Twig):
    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
    <div class="table">
      <table class="table table-hover">
        <thead>
          <tr>
            <th>Ref/id</th>
            <th>Parc's name</th>
            <th>property's number</th>
            <th>Buildings number</th>
            <th></th>
          </tr>
        </thead>
        <tbody>
          {% for parcsproperty in parc %}
          <tr>
            <td>{{ parcsproperty.id }}</td>
            <td>{{ parcsproperty.nom }}</td>
            <td>{{ parcsproperty.ecnt }}</td>
            <td>{{ parcsproperty.bcnt }}</td>
            <td><a href="{{ path('editParcs', {'name': parcsproperty.name}) }}"><button class="btn btn-warning btn-xs">Edit</button></a></td>
          </tr>
          {% endfor %}
        </tbody>
      </table>
    </div>
    Voici la route pour cette vue:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    manage_parcs:
        path:     /manageparcs
        defaults: { _controller: MySpaceMyBundleBundle:MyController:indexParcs }
        requirements:
        methods: GET
    ecnt et bcnt sont juste des alias que j'ai écrit pour faire un count en DQL, ce n'est pas très important ici mais voilà la requête présente dans le controleur de cet vue si vous le souhaitez:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    $query = $em->createQuery('SELECT  p.id, p.nom,
                                        count(distinct b.id) AS bcnt,
                                        count(distinct e.id) AS ecnt
                                       FROM MySpaceDatabaseBundle:Parcsproperty p
                                       LEFT OUTER JOIN  MySpaceDatabaseBundle:Properties e WITH p.id = e.parcsproperty
                                       LEFT OUTER JOIN MySpaceDatabaseBundle:Buildings b WITH e.id = b.ensembles
                                       GROUP BY p.id');
    Maintenant, voici le code de mon entité concerné:
    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
    use Doctrine\ORM\Mapping as ORM;
     
    /**
    * Parcsproperty
    *
    * @ORM\Table(name="parcsproperty")
    * @ORM\Entity
    */
     
    class Parcsproperty
    {
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;
     
    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=150, nullable=false)
     */
    private $name;
     
    //Continue to
    //The getters and the setters and the FK
    Comme vous avez pu le voir dans ma première vue (index avec le tableau), j'ai un bouton edit, qui renvoit sur un formulaire en GET, voici son code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <form action="{{ path('editParcs_process', {'name': name}) }}" method="POST">
      <div>
        {{ form_label(form.name, "Change the name's parc", {'label_attr': {'class': 'control-label'}}) }}
          <div>
            {{ form_widget(form.name, {'attr': {'class': 'form-control'}}) }}
          </div>
      </div>
      <input type="submit" value="Edit" class="btn btn-success"/>
    </form>
    et la route le correspondant (affichage du form en GET, puis une fois validation envoi des données en POST):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    editParcs:
        path:     /manageparcs/edit/{name}
        defaults: { _controller: MySpaceMyBundleBundle:MyController:editAdd }
        requirements:
        methods: GET
     
    editParcs_process:
        path:     /manageparcs/edit/process/{name}
        defaults: { _controller: MySpaceMyBundleBundle:MyController:editAdd }
        requirements:
        methods: POST
    Mon controller concernant cette action, donc cette vu est celui ci:
    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
     public function editAddAction($name) {
        $message="";
        $em = $this->getDoctrine()->getManager();
        $form = $this->createForm(new ParcspropertyType());
        $parc = $em->getRepository('MySpaceDatabaseBundle:Parcsproperty')->findAll();
     
        if (isset($name)) {
            $parc = $em->getRepository('MySpaceDatabaseBundle:Parcsproperty')->find($name);
     
                if (!$parc) {
     
                    $message='no parcs found';
                }
        }
     
        else {
            // add one
            $parc = new Parcspropertyr();
        }
     
        $request = $this->get('request');
     
        if ($request->isMethod('POST') | ($form->isValid())) {
     
                $form->bind($request);
                $parc = $form->getData();
                $parc -> setNom($nom);
                $em->flush();
     
                return $this->redirect($this->generateUrl('manage_parcs'));
            }
     
        else {
                return $this->render('MySpaceMyBundle:MyFolder:editParcs.html.twig', array('form' => $form->createView(), 'parc' => $parc, 'name' => $name));
             }
    }
    Comme vous pouvez le constatez, cette métode du controller editAddAction($nom) {} permet à l'utilisateur de modifier le nom d'un parc selectionné, et si le parc n'existe pas, d'en ajouter/créer un nouveau (bon je suis d'accord, je vais devoir optimiser mon code mieux que ça).

    Toutefois, mon réel problème concernant mon code est celui-ci: symfony me génère aucune erreur mais n'effectue pas l'update. Pourtant dans mon url, concernant mes route, j'ai bien le paramètre en plus affiché {name} comme ceci par exemplelocalhost/MyFolder/MySpace/..//manageparcs/edit/nameOfMySelectedparc.

    Je vous avouerai être un peu perdu là.

    Est ce je m'y prends bien pour l'update? Pourquoi ça ne fonctionne pas?

    (à ce titre, j'ai posté ce problème sur stackoverflow ici si vous préférez)

    Bien à vous

  2. #2
    Membre averti
    Avatar de Dumbeldor
    Homme Profil pro
    Développeur Concepteur Banque postale / Ecole d'ingénieur Alternance
    Inscrit en
    Novembre 2013
    Messages
    88
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 27
    Localisation : France, Landes (Aquitaine)

    Informations professionnelles :
    Activité : Développeur Concepteur Banque postale / Ecole d'ingénieur Alternance

    Informations forums :
    Inscription : Novembre 2013
    Messages : 88
    Points : 301
    Points
    301
    Par défaut
    Ok, mais sans code nous pouvons pas trop t'aider hein.
    N'oubliez pas de mettre un petit pouce vert si mon message vous a aidé !

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2014
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Décembre 2014
    Messages : 24
    Points : 8
    Points
    8
    Par défaut
    Désolé, j'ai cliqué sur l'enregistrement de la discussion avant de faire l'édition complète, je suis allé trop vite (étant nouveau sur le forum, je pense faire deux trois erreurs comme celle-ci, mes excuses d'avance)

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2013
    Messages
    68
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2013
    Messages : 68
    Points : 42
    Points
    42
    Par défaut
    Hello,

    En fait tu ne fait pas de persist pour sauvegarder ton parc. Regarde dans le code la partie après le if( $form->isValid() :

    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
     
    public function editAddAction($name) {
      $parc = $this->get('doctrine')->getRepository('MySpaceDatabaseBundle:Parcsproperty')
        ->findOneByName($name); // On récupère le parc avec le name $name
     
      if( !$parc )
        $parc = new Parcsproperty(); // Si le parc n'existe pas on en crée un nouveau
     
      $form = $this->get('form.factory')->create(new ParcspropertyType(), $parc); // Création du formulaire
      $request = $this->get('request'); // Récupération de la requête
     
      if( $request->isMethod('POST') ) // Si il y a eu un post (donc si j'ai cliqué sur enregistrer)
      {
        $form->bind($request); // Je récupère les valeur postée dans ma requête et on les met dans ton object $parc
     
        if( $form->isValid() ) // Si les données son valide
        {
          $em = $this->getDoctrine()->getManager(); // On récupère le manager de doctrine
          $em->persist($parc); // On persist (création ou modification)
          $em->flush(); // Et on commit nos modifications sur la base de données
     
          return $this->redirect($this->generateUrl('manage_parcs')); // Tout se passe bien on retourne à la liste
        }
      }
     
      return $this->render('MySpaceMyBundle:MyFolder:editParcs.html.twig',
        array(
          'form' => $form->createView(),
          'parc' => $parc,
        )
      );
    }

  5. #5
    Futur Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2014
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Décembre 2014
    Messages : 24
    Points : 8
    Points
    8
    Par défaut
    Alors, je pense avoir compris mon erreur, j'ai édité mon code en fonction de ta réponse Daratar.

    J'ai bien ma valeur name dans mon formulaire. Toutefois, j'ai cette erreur maintenant: Le jeton CSRF est invalide. Veuillez renvoyer le formulaire.

    Je suis en train de fouiner pour savoir comment pallier ça...

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2013
    Messages
    68
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2013
    Messages : 68
    Points : 42
    Points
    42
    Par défaut
    Ce qu'il se passe c'est que pour éviter certaines injection, Symfony a prévu un jeton qui ai envoyé en même temps que le formulaire. Ce jeton s'appelle CSRF.

    Comme tu crées ton formulaire à la main (<form action="" ....>) tu n'as pas de champs jeton crée.

    Ce que tu peux faire c'est ajouter ce champs à la main :
    <input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}">

    Ou bien utiliser une fonction twig {{ form_start(form) }} et mettre à la fin de ton formulaire {{ form_end(form) }}

    Avec ça tu devrais t'en sortir (^_^)

  7. #7
    Futur Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2014
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Décembre 2014
    Messages : 24
    Points : 8
    Points
    8
    Par défaut
    Citation Envoyé par Daratar Voir le message
    Ce qu'il se passe c'est que pour éviter certaines injection, Symfony a prévu un jeton qui ai envoyé en même temps que le formulaire. Ce jeton s'appelle CSRF.

    Comme tu crées ton formulaire à la main (<form action="" ....>) tu n'as pas de champs jeton crée.

    Ce que tu peux faire c'est ajouter ce champs à la main :
    <input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}">

    Ou bien utiliser une fonction twig {{ form_start(form) }} et mettre à la fin de ton formulaire {{ form_end(form) }}

    Avec ça tu devrais t'en sortir (^_^)
    J'ai effectivement opté pour ta deuxième solution rajouter {{ form_start(form) }} et {{ form_end(form) }} avant mon début de balise <form> et après ma fin de balise </form>. Maintenant j'ai une autre erreur: No route found for "POST /manageparcs/edit//Name%20of%20MyParc": Method Not Allowed (Allow: GET, HEAD)

    Et c'est vrai que dans mon url j'ai bel et bien le nom exact de mon parc, avec en plus les " % ", ça je ne sais pas pourquoi. Ce n'est pas bon n'est-ce pas? de plus, j'ai l'impression qu'il cherche la route /manageparcs/edit/{name} en POST alors qu'elle est en GET, au lieu de celle qui gère l'envoi en POST cad /manageparcs/edit/process/{name}.

    C'est une bonne façon de faire que de rajouter {{ form_start(form) }}, ne devrais-je pas plutôt utiliser les FormType de Symfony en implémentant le widget dans mon code ainsi {{ form_widget (form) }} ?

  8. #8
    Futur Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2014
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Décembre 2014
    Messages : 24
    Points : 8
    Points
    8
    Par défaut
    Citation Envoyé par ju_dev Voir le message
    Et c'est vrai que dans mon url j'ai bel et bien le nom exact de mon parc, avec en plus les " % ", ça je ne sais pas pourquoi.
    Je suppose en fait que les " % " sont les espaces entres les mots !!!

  9. #9
    Futur Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2014
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Décembre 2014
    Messages : 24
    Points : 8
    Points
    8
    Par défaut
    Citation Envoyé par ju_dev Voir le message
    J'ai effectivement opté pour ta deuxième solution rajouter {{ form_start(form) }} et {{ form_end(form) }} avant mon début de balise <form> et après ma fin de balise </form>. Maintenant j'ai une autre erreur: No route found for "POST /manageparcs/edit//Name%20of%20MyParc": Method Not Allowed (Allow: GET, HEAD)
    Bon j'ai corrigé mon erreur, et grâce à Daratar aussi par ailleurs. En fait, tu avais raison, il faut bien rajouter {{ form_start(form) }} et {{ form_end(form) }} mais entre les balises <form></form>, erreur de débutant. Et bien entendu l'update fonctionne.

    Par contre maintenant, là ou j'ai un autre souci: le fait d'avoir rajouter {{ form_start(form) }} et {{ form_end(form) }} m'affiche tous les inputs de tous les champs de mon entité dans mon formulaire, hors à la base je ne veux que celui des noms. Des idées? je fouine encore.

  10. #10
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2013
    Messages
    68
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2013
    Messages : 68
    Points : 42
    Points
    42
    Par défaut
    Reuh !

    C'est normal en fait. Quand tu utilises form_start / form_end il vas t'afficher TOUT le contenu de ton formulaire.

    Ce que tu peux faire c'est créer un autre form type avec un nom différent du premier ou ta fonction de buildForm ressemblerais à ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name', null,
                array(
                    'label' => 'Nom du parc',
                    'attr' => array(
                      'class' => 'form-control',
                    )
                )
            )
        ;
    }
    Si tu regardes bien, le controller que je t'ai filer (enfin la fonction addeditAction) permet de tout faire afficher le formulaire, afficher les erreurs en cas d'erreurs et enregistrer puis rediriger quand tout va bien. Donc tu pourrais avoir une unique route comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    editParcs:
        path:     /manageparcs/edit/{name}
        defaults: { _controller: MySpaceMyBundleBundle:MyController:editAdd }
    Et dans ton twig tu n'aurais que ça : (pas besoin de balise <form> il va le faire tout seul).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    {{ form_start(form) }}
    <div>
      {{ form_label(form.name) }}
        <div>
          {{ form_widget(form.name) }}
        </div>
    </div>
    <input type="submit" value="Edit" class="btn btn-success"/>
    {{ form_end(form) }}
    Je sais que je vais un peu plus loin que ta question donc pour répondre simplement.

    La fonction twig form_start() va créer TOUT les champs que contient ton form type.

  11. #11
    Futur Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2014
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Décembre 2014
    Messages : 24
    Points : 8
    Points
    8
    Par défaut
    Citation Envoyé par Daratar Voir le message
    Reuh !

    C'est normal en fait. Quand tu utilises form_start / form_end il vas t'afficher TOUT le contenu de ton formulaire.

    Ce que tu peux faire c'est créer un autre form type avec un nom différent du premier ou ta fonction de buildForm ressemblerais à ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name', null,
                array(
                    'label' => 'Nom du parc',
                    'attr' => array(
                      'class' => 'form-control',
                    )
                )
            )
        ;
    }
    Si tu regardes bien, le controller que je t'ai filer (enfin la fonction addeditAction) permet de tout faire afficher le formulaire, afficher les erreurs en cas d'erreurs et enregistrer puis rediriger quand tout va bien. Donc tu pourrais avoir une unique route comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    editParcs:
        path:     /manageparcs/edit/{name}
        defaults: { _controller: MySpaceMyBundleBundle:MyController:editAdd }
    Et dans ton twig tu n'aurais que ça : (pas besoin de balise <form> il va le faire tout seul).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    {{ form_start(form) }}
    <div>
      {{ form_label(form.name) }}
        <div>
          {{ form_widget(form.name) }}
        </div>
    </div>
    <input type="submit" value="Edit" class="btn btn-success"/>
    {{ form_end(form) }}
    Je sais que je vais un peu plus loin que ta question donc pour répondre simplement.

    La fonction twig form_start() va créer TOUT les champs que contient ton form type.
    Non Justement ta réponse m'aide. j'ai une base de données ayant plus de 100 tables, donc 100 entités. Avec Doctrine, j'ai généré tous les FormType pour justement ne pas avoir à créer des formulaire pour l'administration de ma base en interne dans l'application web.
    Du coup grâce à cela j'appelle mes formulaire en faisant ceci {{ form_widget (form) }}. Je souhaite rester sur une même directive et perspective de dev, histoire d'avoir un code propre et cohérent, qu'en penses-tu?
    Je pense que je devrais plutôt m'en servir. je vais me pencher dessus ce soir, et posterai ce que j'ai touvé. Mais merci de ta réponse je vais aussi m'appuyer sur cela.

  12. #12
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2013
    Messages
    68
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2013
    Messages : 68
    Points : 42
    Points
    42
    Par défaut
    Reuh !
    Bien dormi ?
    Tu peux conserver les fonctions from_widget si tu veux, là y'a pas de soucis (oubli pas de mettre form_errors de la même façon).
    Par contre dans le cas ou tu ne veux pas créer de nouveau form type, tu ne peux pas appeler la fonction form_start. Du coup du dois passer par les balises <form></form> et ajouter le CSRF à la main :
    <input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}">

    Je me suis cassé les dents la dessus aussi quand j'ai commencé (mais pourquoi il m'affiche tout alors que moi j'en veux que deux >_<).

  13. #13
    Futur Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2014
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Décembre 2014
    Messages : 24
    Points : 8
    Points
    8
    Par défaut
    Citation Envoyé par Daratar Voir le message
    Reuh !
    Bien dormi ?
    Tu peux conserver les fonctions from_widget si tu veux, là y'a pas de soucis (oubli pas de mettre form_errors de la même façon).
    Par contre dans le cas ou tu ne veux pas créer de nouveau form type, tu ne peux pas appeler la fonction form_start. Du coup du dois passer par les balises <form></form> et ajouter le CSRF à la main :
    <input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}">

    Je me suis cassé les dents la dessus aussi quand j'ai commencé (mais pourquoi il m'affiche tout alors que moi j'en veux que deux >_<).
    Salut daratar, alors oui bien dormi. J'ai passé une bonne parti de ma soirée sur ce soucis. Et comme tu viens de le dire, c'est à se casser les dents contre les coins de ton bureau! J'ai toutefois peut être trouvé la solution, je la poste dès que j'ai fini. Merci pour ton coup de main. Je débute tout juste sur Symfony, j'ai un an de dev dans les pattes et je suis actuellement en alternance et surtout en auto-gestion dans une boîte qui ne fait pas de dev, donc pas facile parfois mais ça me plaît bien.

    Rajouter le CRSF à la main c'est propre?

    De toute façon je vais devoir trouvé le meilleur compromis (ta solution m'a beaucoup éclairé sur ce point). Ce schéma de création de formulaire pour modifier/ajouter les données va être mis en place plusieurs fois dans mon projet pour mes différentes entités, c'est juste la façon de faire qui va différer.

    Je reviens vers toi dès que j'ai ma solution, et si je n'ai pas le rendu espérer, je vais utiliser la tienne et l'implémenter correctement dans mon projet.

  14. #14
    Futur Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2014
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Décembre 2014
    Messages : 24
    Points : 8
    Points
    8
    Par défaut
    Bon du coup j'ai utilisé ceci dans ma twig pour générer le formulaire que j'ai créer avec Doctrine suivant mes entités:
    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
    <form action="{{ path('modifierParcs_process', {'nom': parc.nom}) }}" method="POST">
                              {# Les erreurs générales du formulaire. #}
                              {{ form_errors(form) }}
                              {# Jeton CSRF à rajouter #}
                              <input type="hidden" name="_token" value="{{ csrf_token('authenticate') }}">
                              <div>
                                {# Génération du label. #}
                                {{ form_label(form.nom, "Nom du Parc:", {'label_attr': {'class': 'control-label'}}) }}
                                {# Affichage des erreurs pour ce champ précis. #}
                                {{ form_errors(form.nom) }}
                                <div>
                                {# Génération de l'input. #}
                                {{ form_widget(form.nom, {'attr': {'class': 'form-control'}}) }}
                                </div>
                              </div>
    {# validation #}
                              <input type="submit" value="Valider les modifications" class="btn btn-warning"/>
                            </form>
    Toutefois j'ai bien l'erreur du jeton CSRF, j'ai donc écrit rajouter ces lignes dans mon formType ParcspropertyType:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    public function setDefaultOptions(OptionsResolverInterface $resolver)
        {
            $resolver->setDefaults(array(
                'data_class' => 'MySpace\DatabaseBundle\Entity\Parcproperty',
                'csrf_protection' => null,
                'csrf_field_name' => '_token',
            ));
        }
    Le fait de setter la 'csrf_protection' à null c'est grave? Sachant que dans mon config.yml j'ai mis ce champ:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        form:            ~
        csrf_protection: true
    Je me suis servi de la doc de symfony ici.

  15. #15
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2013
    Messages
    68
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2013
    Messages : 68
    Points : 42
    Points
    42
    Par défaut
    Yop,

    Désactivé la protection CSRF c'est jamais positif mais c'est pas tout le temps négatif.
    En fait tu peux créer un formulaire dans un mail et cacher les données, tu crée ton submit sous form de lien et tu envoi à l'admin. Il clic sur le lien et comme lui il a les droits bas ça enregistre les soumissions du post.
    Si la protection est activé, symfony va se dire "bah ce formulaire vient pas de moi, je bloque et je demande mon jeton".

    Le fait d'ajouter la ligne <input type="hidden" name="_token" value="{{ csrf_token('authenticate') }}"> devrait te permettre de ne pas enlever la protection, ça ne marche pas ?

  16. #16
    Futur Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2014
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Décembre 2014
    Messages : 24
    Points : 8
    Points
    8
    Par défaut
    Citation Envoyé par Daratar Voir le message
    Yop,

    Désactivé la protection CSRF c'est jamais positif mais c'est pas tout le temps négatif.
    En fait tu peux créer un formulaire dans un mail et cacher les données, tu crée ton submit sous form de lien et tu envoi à l'admin. Il clic sur le lien et comme lui il a les droits bas ça enregistre les soumissions du post.
    Si la protection est activé, symfony va se dire "bah ce formulaire vient pas de moi, je bloque et je demande mon jeton".

    Le fait d'ajouter la ligne <input type="hidden" name="_token" value="{{ csrf_token('authenticate') }}"> devrait te permettre de ne pas enlever la protection, ça ne marche pas ?
    Si je rajoute la ligne <input type="hidden" name="_token" value="{{ csrf_token('authenticate') }}"> comme tu me suggère de le faire, Symfony me génère l'erreur quand même en enlevant bien sûr les lignes ajoutées suivante dans mon formType ParcspropertyType:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    'csrf_protection' => null,
                'csrf_field_name' => '_token',
    .

    Sachant que de toute manière ce formulaire ne sera accessible que si le user est connecté est-ce réellement grave? Je vais quand même fouiller pour savoir pourquoi il me génère toujours l'erreur.

  17. #17
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    725
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Juin 2011
    Messages : 725
    Points : 1 050
    Points
    1 050
    Par défaut
    Bonjour,

    Si j'ai bien suivi ta problématique est juste de ne pas afficher tous les champs de formulaire.
    Pourquoi ne pas les supprimer de la méthode buildForm?
    S'ils sont présent dans buildForm mais pas dans le template html, et donc non transmis sur le POST, la validation échouera de toute façon (en plus de l'echec de la validation du csrf_token...).


    Si tu veux + de souplesse sans avoir à créer + sieurs formulaire pour une même entité, tu peux ajouter une option à ton form type
    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
    class MonFormType{
    
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        //on gère 2 cas un formulaire simple avec un minimum de champ et un formulaire + complet
        $builder->add('name');
        //...
       if($options['mode']=='full'){
         $builder->add('adress');
         //...
       }
    }
    public function setDefaultOptions(OptionsResolverInterface $resolver)
        {
            $resolver->setDefaults(array(
                'data_class' => 'MySpace\DatabaseBundle\Entity\Parcproperty',
                'mode'=>'simple' 
            ))
            ->setAllowedValues(array('mode'=>array('simple','full'));
        }
    }
    Dans le controller
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    //form en mode simple
    $this->createForm(new MonFormType,$entity);
    
    //form en mode complet
    $this->createForm(new MonFormType,$entity,array('mode'=>'full'));

  18. #18
    Futur Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2014
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Décembre 2014
    Messages : 24
    Points : 8
    Points
    8
    Par défaut
    Citation Envoyé par arnooo999 Voir le message
    Bonjour,

    Si j'ai bien suivi ta problématique est juste de ne pas afficher tous les champs de formulaire.
    Pourquoi ne pas les supprimer de la méthode buildForm?
    S'ils sont présent dans buildForm mais pas dans le template html, et donc non transmis sur le POST, la validation échouera de toute façon (en plus de l'echec de la validation du csrf_token...).


    Si tu veux + de souplesse sans avoir à créer + sieurs formulaire pour une même entité, tu peux ajouter une option à ton form type
    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
    class MonFormType{
    
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        //on gère 2 cas un formulaire simple avec un minimum de champ et un formulaire + complet
        $builder->add('name');
        //...
       if($options['mode']=='full'){
         $builder->add('adress');
         //...
       }
    }
    public function setDefaultOptions(OptionsResolverInterface $resolver)
        {
            $resolver->setDefaults(array(
                'data_class' => 'MySpace\DatabaseBundle\Entity\Parcproperty',
                'mode'=>'simple' 
            ))
            ->setAllowedValues(array('mode'=>array('simple','full'));
        }
    }
    Dans le controller
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    //form en mode simple
    $this->createForm(new MonFormType,$entity);
    
    //form en mode complet
    $this->createForm(new MonFormType,$entity,array('mode'=>'full'));
    arnooo999, je ne fais pas cette méthode (j'y ai pensé) tout simplement car j'ai généré le buildform avec doctrine, en rapport avec mes entités. Doctrine m'a donc généré un dossier Form, avec un $buildform pour mes 100 tables. Comme il va y avoir de la gestion de la base de données par l'admin (côté CMS si je puis dire grossièrement), en effaçant des champs, je les effacent totalement, donc l'administration de la base va être malmené. Surtout que je fais appel à ce formulaire aussi pour l'ajout, la suppression. Le mieux est donc de choisir de ne pas mettre les champs que je ne veux pas dans ma twig, et non dans la buildform. Enfin, ce n'est que mon avis, mais aussi une contrainte du client. Qu'en penses-tu?

  19. #19
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    725
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Juin 2011
    Messages : 725
    Points : 1 050
    Points
    1 050
    Par défaut
    Si un champ est présent dans ton entité mais pas dans ton formulaire, il n'y a simplement pas de synchro entre les données saisie et l'attribut.
    La valeur en base reste donc inchangé.

  20. #20
    Futur Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2014
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Décembre 2014
    Messages : 24
    Points : 8
    Points
    8
    Par défaut
    Bien sûr je suis d'accord.

    Toutefois, comme je fais appel ce FormType plusieurs foi (une fois pour un update, une fois pour un ajout, une autre fois pour supprimer etc etc etc) et que à certains moment j'ai besoin de tous les champs, et d'autres fois non, il est plus simple d'enlever ces champs pour un cas précis dans ma twig plutôt que dans mon buildform je penses.

Discussions similaires

  1. Peut on ajouter des champs dans l'entité Note
    Par VITALTH dans le forum Microsoft Dynamics CRM
    Réponses: 3
    Dernier message: 18/02/2014, 14h42
  2. [MySQL] Ajouter des données dans une table avec la cmd update
    Par pierrot10 dans le forum PHP & Base de données
    Réponses: 7
    Dernier message: 25/09/2007, 20h54
  3. INSERER DU TEXTE AVEC DES CHAMPS DANS UNE REQUETE SUR sql Srv 2000
    Par sauceaupistou dans le forum MS SQL Server
    Réponses: 1
    Dernier message: 24/03/2007, 11h02
  4. updater des données dans mon fichier excel
    Par gantec dans le forum Macros et VBA Excel
    Réponses: 9
    Dernier message: 26/02/2007, 17h01
  5. Ajouter des champ dans une table avec une procedure sp
    Par Abdou1 dans le forum MS SQL Server
    Réponses: 5
    Dernier message: 26/07/2006, 19h32

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