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 :

Liste de checkbox et erreur "The CSRF token is invalid. Please try to resubmit the form"


Sujet :

Symfony PHP

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    90
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 90
    Points : 54
    Points
    54
    Par défaut Liste de checkbox et erreur "The CSRF token is invalid. Please try to resubmit the form"
    Bonjour,

    Je rencontre quelques soucis dans l'implémentation d'un formulaire de gestion de catégorie.

    En faites, je souhaite faire une page qui permet de manager les catégories, et donc d'ajouter et supprimer des catégories (on verra plus tard pour permettre la modification :p)

    Ma partie ajout de catégorie fonctionne bien, maintenant j'ai voulu faire un 2eme formulaire sur la page permettant la suppression d'une ou plusieurs catégories à la fois en me servant de checkbox pour sélectionner celles à supprimer, malheureusement ça ne fonctionne pas.

    Je n'ai pas encore implémenté le code qui fait la suppression des catégories dans ma base de donnée, mais j'ai déjà un soucis lors de la validation du formulaire avec le message d'erreur: The CSRF token is invalid. Please try to resubmit the form.

    Voici mon code:

    Controller:
    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
     
    <?php
     
    namespace XXXBundle\Controller;
     
    use Symfony\Bundle\FrameworkBundle\Controller\Controller;
    use XXXBundle\Entity\Category;
    use XXXBundle\Form\CategoryType;
    use Symfony\Component\HttpFoundation\Request;
     
    class AdminController extends Controller
    {
     
        public function manageCategoryAction(Request $request)
        {
        	$category = new Category();
        	$form = $this->createForm(new CategoryType(), $category);
     
        	$request = $this->get('request');
     
         	if ($request->getMethod() == 'POST') {
        		$form->bindRequest($request);
        		//TODO: identifier si action add ou delete
        		if ($form->isValid()){
    	    		if ($request->get('action') == 'addCategory') {
    					$this->addCategoryAction($category);
    					$form = $this->createForm(new CategoryType(), new Category());
    	    		} elseif ($request->get('action') == 'deleteCategory') {
    	    			//TODO
    	    		}
        		}
        	}
     
        	$cr = $this->getDoctrine()->getRepository('XXXBundle:Category');
        	$categories = $cr->findAllOrderedByName(); 
     
     
     
        	return $this->render('XXXBundle:Admin:category.html.twig', array(
        			'form' => $form->createView(),
        			'categories' => $categories,
        	));
        }
     
        public function addCategoryAction(Category $category)
        {
            	$em = $this->getDoctrine()->getEntityManager();
            	$em->persist($category);
            	$em->flush();
        }
    }
    ma classe définissant la form (que pour l'ajout du coup):
    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
     
    <?php
    namespace XXXBundle\Form;
     
    use Symfony\Component\Form\AbstractType;
    use Symfony\Component\Form\FormBuilder;
    use XXXBundle\Entity\Category; 
    use XXXBundle\Repository\CategoryRepository;
     
     
    class CategoryType extends AbstractType
    {
    	public function buildForm(FormBuilder $builder, array $options)
        {
     
            $builder->add('name', 'text', array('label' => 'Nom'))
            		->add('parent','entity',array(
    	        		'class'=>'XXXBundle:Category',
    	        		'property'=>'name',
    	        		'label'=>'Choix de categorie parent',
        				'query_builder' => function(CategoryRepository $cr){ return $cr->getMainCategoriesQb(); },
    		            'required'=>false,
    		            'empty_value'=>'(Aucune)',));
        }
     
    	public function setDefaultOptions(OptionsResolverInterface $resolver)
    	{
    		$resolver->setDefaults(array(
    				'data_class' => 'XXXBundle\Entity\Category',
    		));
    	}
     
    	public function getName()
    	{
    		return 'category';
    	}
    }
    Mon template twig pour l'affichage des formulaire:
    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
     
    {% extends 'XXXBundle:Admin:base.html.twig' %}
     
    {% block title %}
    	Gestion des categories 
    {% endblock %}
     
    {% block body %}
    	Gestion des categories
     
    	<form action="{{ path('_manageCategory') }}" method="post" {{ form_enctype(form) }} name="addCategory">
        	{{ form_widget(form) }}
    		<input type="hidden" id="action" name="action" value="addCategory" />
        	<input type="submit" value="Ajouter"/>
    	</form>
     
     
    	<form action="{{ path('_manageCategory') }}" method="post" {{ form_enctype(form) }} name="deleteCategory">
    		{% for category in categories %}
    	        <li>
    	        	<span>{{ category.name }} </span>
    		        <span>
    		        {% if category.parent|length>0 %} 
    		        	{{ category.parent.name }} 
    		        {% else %} 
    		        	N/A 
    		        {% endif %} 
    		        </span>
    		        <span>
    		        	<input type="checkbox" name="id" value="{{ category.id }}" {% if category.children|length>0 %}disabled{% endif %} />
    		        </span>
    	        </li>
    	    {% endfor %}
    	    {{ form_rest(form) }}
    	    <input type="hidden" id="action" name="action" value="deleteCategory" />
        	<input type="submit" value="Supprimer"/>
        </form>
     
     
    {% endblock %}
    Et mon Entité Category:
    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
     
    <?php
    namespace XXXBundle\Entity;
     
    use Doctrine\ORM\Mapping\ManyToOne;
    use Doctrine\Common\Collections\ArrayCollection;
    use Doctrine\ORM\Mapping as ORM;
    use Symfony\Component\Validator\Constraints as Assert;
    use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
     
    /**
     * @ORM\Entity(repositoryClass="XXXBundle\Repository\CategoryRepository")
     * @ORM\Table(name="category")
     * @UniqueEntity(fields="name",message="Le nom de la catégorie doit être unique!") 
     */
    class Category
    {
    	/** 
    	 * @ORM\Id 
    	 * @ORM\Column(name="id", type="integer") 
    	 * @ORM\GeneratedValue(strategy="AUTO") 
    	 */
        private $id;
     
        /** 
         * @var string $name
         * 
         * @ORM\Column(name="name", type="string", length=100, unique=true) 
         */
        private $name;
     
        /**
         * @ORM\OneToMany(targetEntity="Activity", mappedBy="category")
         */
        private $activity;
     
        /**
         * @ORM\OneToMany(targetEntity="Category", mappedBy="parent")
         */
        private $children;
     
        /**
         * @ORM\ManyToOne(targetEntity="Category", inversedBy="children")
         * @ORM\JoinColumn(name="parent_id", referencedColumnName="id")
         */
        private $parent;
     
     
        public function __construct()
        {
            $this->activity = new \Doctrine\Common\Collections\ArrayCollection();
        	$this->children = new \Doctrine\Common\Collections\ArrayCollection();
        }
     
        /**
         * Get id
         *
         * @return integer 
         */
        public function getId()
        {
            return $this->id;
        }
     
        /**
         * Set name
         *
         * @param string $name
         */
        public function setName($name)
        {
            $this->name = $name;
        }
     
        /**
         * Get name
         *
         * @return string 
         */
        public function getName()
        {
            return $this->name;
        }
     
        /**
         * Add activity
         *
         * @param XXXBundle\Entity\Activity $activity
         */
        public function addActivity(\XXXBundle\Entity\Activity $activity)
        {
            $this->activity[] = $activity;
        }
     
        /**
         * Get activity
         *
         * @return Doctrine\Common\Collections\Collection 
         */
        public function getActivity()
        {
            return $this->activity;
        }
     
        /**
         * Add children
         *
         * @param XXXBundle\Entity\Category $children
         */
        public function addCategory(\XXXBundle\Entity\Category $children)
        {
            $this->children[] = $children;
        }
     
        /**
         * Get children
         *
         * @return Doctrine\Common\Collections\Collection 
         */
        public function getChildren()
        {
            return $this->children;
        }
     
        /**
         * Set parent
         *
         * @param XXXBundle\Entity\Category $parent
         */
        public function setParent(\XXXBundle\Entity\Category $parent)
        {
            $this->parent = $parent;
        }
     
        /**
         * Get parent
         *
         * @return XXXBundle\Entity\Category 
         */
        public function getParent()
        {
            return $this->parent;
        }
     
    }
    Mon but étant bien sûr d'afficher les catégories existantes sous forme d'un tableau, avec la dernière colonne permettant de sélectionner via une checkbox uniquement les catégories supprimables (par les catégories parent avec des enfants rattachés dessus).

    Des suggestions? J'ai vu qu'il y avait une histoire de champ _token pour palier a ce probleme, mais mon form_rest(form) n'est surement pas bon (vu qu'il utilise l'objet form du formulaire d'ajout au dessus) mais je ne vois pas comment bien procéder tout en étant carré pour arriver à mes fins...

    Des suggestions?

  2. #2
    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
    tu as deux formulaire html dans ton template twig,le jeton est présent uniquement dans le premier.
    le second formulaire n'est pas du tout géré pas par ton CategoryType, alors pourquoi faire un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $form->bindRequest($request);...
    créer plutôt deux actions dans ton controller pour gérer les deux cas (ajout et suppression), ce sera plus simple.
    Ou bien regarde du coté du type Collection: http://symfony.com/doc/2.0/reference...ollection.html

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    90
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 90
    Points : 54
    Points
    54
    Par défaut
    Désolé je débute dans Symfony et je ne m'y connais pas très bien.

    Mais du coup si je crée une 2eme action, vu qu'à la fin de l'action je veux que la page qui soit render contienne le même formulaire, je vais du coup avoir les mêmes lignes de code dans mon action (avec la création de l'objet form et le render derrière...)...

    J'ai l'impression de ne pas m'y prendre comme il faut... Des conseils sur comment vraiment bien architecturer mon controller et prendre en compte mes 2 actions sur la même page?

  4. #4
    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
    tu peux toujours factoriser des méthodes dans ta classe controller.
    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
     
    class Controller{
     
    /**
    * @var Form
    **/ 
     
    protected $form;
    /**
    * @var array <Category>
    */
    protected $categories;
     
    //appelé par GET
    public function indexAction(){
       return $this->renderCategoryTemplate();
    }
     
    //appelé par POST
    public function addAction(){
      $data=array();
       $form=$this->getForm();
       $form->bindRequest($this->getRequest);
       if($form->isValid()){
          //persister l'entité
         // et envoyer un message flash
       }
       return $this->renderCategoryTemplate();
    }
     
    //appelé par POST
    public function deleteAction(){
       //récupérer les id  et supprimer les entités
       return $this->renderCategoryTemplate();
    }
     
    /**
    * @return Response
    **/
    protected function renderCategoryTemplate($data=array()){
            $data['form']=$this->getForm()->createView();
            $data['categories']=$this->getCategories();
            return $this->render('XXXBundle:Admin:category.html.twig', $data);
    }
     
    /**
    * @return Form
    **/
    protected function getForm(){
       if(null===$this->form){
            $category = new Category();
        	$this->form = $this->createForm(new CategoryType(), $category);
       }
       return $this->form;
    }
     
    /**
    * @return array<Category>
    **/
    protected function getCategories(){
        if(null===$this->categories){
            $cr = $this->getDoctrine()->getRepository('XXXBundle:Category');
        	$this->categories = $cr->findAllOrderedByName(); 
       }
       return $this->categories;
    }
     
    }
    il y a également un tag trés utile dans Twig qui permet de renvoyer le contenu d'un controller
    http://symfony.com/doc/2.0/book/templating.html#index-8
    mais dans ce cas précis, je ne pense pas que ça conviendra.

  5. #5
    Membre habitué Avatar de anta_res
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2006
    Messages
    93
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Mai 2006
    Messages : 93
    Points : 173
    Points
    173
    Par défaut
    Personnellement dans ce cas je me pencherai plutôt vers le type collection http://symfony.com/fr/doc/current/co...llections.html

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    90
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 90
    Points : 54
    Points
    54
    Par défaut
    arnooo999:

    Merci pour cette suggestion. Dans le code que tu proposes, y a t il une raison pour que tu ajoutes les variables categories et form, qu'est ce que cela permet de plus par rapport à mon code qui ne variabilisait pas ces éléments?

    Aussi, je voulais essayer de garder la même url pour l'ajout et la suppression lorsque l'on lance une action d'ajout ou de suppression (à savoir toujours pointer vers manage-category) pour essayer de faire comme sur certains sites où l'on voit l'url inchangée, mais j'imagine qu'avec ton code je vais devoir définir différentes routes du coup pour pouvoir déclencher chacune des actions?

    anta_res:

    Je suis en train de voir le tutoriel avec les Collection, ça a l'air de bien correspondre à ce que je recherche pour faire mon formulaire de catégories
    Mais du coup, je vais être obligé de rajouter un niveau d'abstraction qui aura une collection de categories?
    Ou je peux faire quelquechose du style:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    $cr = $this->getDoctrine()->getRepository('XXXBundle:Category');
    $categories = $cr->findAllOrderedByName(); 
     
    $form = $this->createForm(new CategoryType(), $categories);

Discussions similaires

  1. [2.x] "The CSRF token is invalid"
    Par keokaz dans le forum Symfony
    Réponses: 1
    Dernier message: 08/11/2012, 10h19
  2. Réponses: 1
    Dernier message: 01/05/2012, 13h33
  3. [Javascript] Listes liées en Javascript + erreurs invisibles
    Par MinsK dans le forum Général JavaScript
    Réponses: 19
    Dernier message: 11/05/2006, 15h00
  4. [JSP] Liste de checkboxes 2 niveaux de hiérarchie dans form
    Par belgianbaloo dans le forum Servlets/JSP
    Réponses: 2
    Dernier message: 21/09/2005, 09h59

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