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 :

ajout d'un lien delete en index


Sujet :

Symfony PHP

  1. #1
    Membre du Club
    Femme Profil pro
    Inscrit en
    Avril 2011
    Messages
    127
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2011
    Messages : 127
    Points : 49
    Points
    49
    Par défaut ajout d'un lien delete en index
    Sur ma page index, j'ai un tableau qui liste les différents commentaires.
    Je souhaite ajouter, à côté de chaque commentaire, une action qui permette de supprimer un commentaire, comme ceci:

    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
     
    <table class="table table-striped table-bordered table-hover" id="dataTables-example">
                <thead>
                    <tr>
                        <th class="text-center">#</th>
                        <th class="text-center">Auteur</th>
                        <th class="text-center">Contenu</th>
                        <th class="text-center">Date de création</th>
                        <th class="text-center">Tutoriel lié</th>
                        <th class="text-center">Statut</th>
                        <th class="text-center">Actions</th>
                    </tr>
                </thead>
                <tbody>
                    {% for entity in entities %}
                        <tr class="odd gradeX">
                            <td>{{ entity.id }}</td>
                            <td>{{ entity.user }}</td>
                            <td>{{ entity.content }}</td>
                            <td class="text-center">{% if entity.createdAt %}{{ entity.createdAt|date('Y-m-d H:i:s') }}{% endif %}</td>
                            <td>{{ entity.tutorial.title }}</td>
                            <td>{{ entity.status }}</td>
                            <td class="table-action">
                                <a href="{{ path('admin_comment_show', { 'id': entity.id }) }}">
                                    Voir la fiche du commentaire - 
                                </a>
                                <a href="{{ path('admin_comment_edit', { 'id': entity.id }) }}">
                                    Editer - 
                                </a>
                                <a href="{{ path('admin_comment_delete', { 'id': entity.id }) }}">
                                    Supprimer - 
                                </a>   
     
                            </td>
                        </tr>
                    {% endfor %}
                </tbody>
            </table>
    Lorsque je fais ceci, et que je clique sur "supprimer", j'ai cette erreur: No route found for "GET /admin/comment/delete/8": Method Not Allowed (Allow: POST, DELETE)

    J'ai lu plusieurs explications, et j'ai bien compris que la suppression devait se faire via un <form>, pour la protection CSRF.
    Seulement voilà, je suis perdue...

    Actuellement, voici les actions du controller qui gèrent la suppression:

    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
     
    /**
         * Deletes a Comment entity.
         * @Route("/delete/{id}", name="admin_comment_delete")
         * @Method("DELETE")
         *
         */
        public function deleteAction(Request $request, $id)
        {
            $form = $this->createDeleteForm($id);
            $form->submit($request);
     
            if ($form->isValid()) {
                $em = $this->getDoctrine()->getManager();
                $entity = $em->getRepository('SiteFrontBundle:Comment')->find($id);
     
                if (!$entity) {
                    throw $this->createNotFoundException('Unable to find Comment entity.');
                }
     
                $em->remove($entity);
                $em->flush();
            }
     
            return $this->redirect($this->generateUrl('admin_comment'));
        }
     
        /**
         * Creates a form to delete a Comment entity by id.
         *
         * @param mixed $id The entity id
         *
         * @return \Symfony\Component\Form\Form The form
         */
        private function createDeleteForm($id)
        {
            return $this->createFormBuilder(array('id' => $id))
                        ->add('id', 'hidden')
                        ->getForm();
        }
    L'action index:

    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
     
    /**
         * Lists all Comment entities.
         *
         */
        public function indexAction()
        {
            $em = $this->getDoctrine()->getManager();
     
            $entities = $em->getRepository('SiteFrontBundle:Comment')->findAll();
     
            return $this->render('SiteFrontBundle:Admin/Comment:index.html.twig', array(
                'entities' => $entities,
            ));
        }
    Et voici ma route:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    admin_comment_delete:
        path:     /delete/{id}
        defaults: { _controller: "SiteFrontBundle:Admin/Comment:delete" }
        requirements: { _method: post|delete }
    Pourriez-vous m'aider svp? D'avance merci

  2. #2
    Membre averti

    Inscrit en
    Juin 2008
    Messages
    307
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 307
    Points : 364
    Points
    364
    Par défaut
    Le @Method de ton action n'est pas bon , il faut mettre : * @Method("GET") car tu passe par un lien.

    Olivier

  3. #3
    Membre du Club
    Femme Profil pro
    Inscrit en
    Avril 2011
    Messages
    127
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2011
    Messages : 127
    Points : 49
    Points
    49
    Par défaut
    Merci d'avoir pris la peine de répondre.

    Par contre, modifier la méthode en GET ne sert à rien: plus de message d'erreur, c'est vrai, mais la suppression ne se fait pas en base de données.
    Je pense également que passer par la méthode GET n'est pas la bonne solution, puisque dans ce cas il y aurait un souci au niveau du CSRF.

    Mon problème est exactement le même que celui décrit ici: http://symfony.com/fr/doc/current/co...arameters.html, mais l'exemple n'est pas complet et j'ai du mal

    Mais je n'arrive pas à bien comprendre..

  4. #4
    Membre averti

    Inscrit en
    Juin 2008
    Messages
    307
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 307
    Points : 364
    Points
    364
    Par défaut
    Si le fait d'avoir mis la méthode GET à la place de DELETE a fait en sorte que le controller trouve ton action (d'ailleurs le message était plutôt clair). Le fait que l'entité ne soit pas supprimé est un autre problème plutôt lié à ta requête, je pense que entre le remove et le flush tu as oublié $em->persist().

  5. #5
    Membre du Club
    Femme Profil pro
    Inscrit en
    Avril 2011
    Messages
    127
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2011
    Messages : 127
    Points : 49
    Points
    49
    Par défaut
    Euh... sérieusement, je ne pense pas qu'il faille un persist dans une action delete.
    Voici ce qui est dit dans la doc de symfony:

    Supprimer un objet
    Supprimer un objet est très similaire, mais requiert un appel à la méthode remove() du gestionnaire d'entités :

    $em->remove($product);
    $em->flush();

    Comme vous vous en doutez, la méthode remove() signale à Doctrine que vous voulez supprimer l'entité de la base de données. La vraie requête DELETE, cependant, n'est réellement exécutée que lorsque la méthode flush() est appelée.

  6. #6
    Membre averti

    Inscrit en
    Juin 2008
    Messages
    307
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 307
    Points : 364
    Points
    364
    Par défaut
    Effectivement.
    Quand tu regarde au niveau de la toolbar symfony, est ce qu'il passe une requête si oui sur quel id ?

    A mon avis c'est au niveau de ton $form->isValid() que ca ne doit pas fonctionner et du coup tu retourne sur la page qui liste tes entités. Essaie de retourner une exception quand ton formulaire n'est pas valide

    Olivier

  7. #7
    Membre du Club
    Femme Profil pro
    Inscrit en
    Avril 2011
    Messages
    127
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2011
    Messages : 127
    Points : 49
    Points
    49
    Par défaut
    Salut ;-)

    Non, pas de requête à l'horizon quand je pointe le bouton de suppression..
    Du coup, j'ai fait ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    if ($form->isValid()) {
                $em = $this->getDoctrine()->getManager();
                $entity = $em->getRepository('SiteFrontBundle:Comment')->find($id);
     
                if (!$entity) {
                    throw $this->createNotFoundException('Unable to find Comment entity.');
                }
     
                $em->remove($entity);
                $em->flush();
            }else{
                throw $this->createNotFoundException('Il y a un souci...');
            }
    et effectivement, l'exception est là.

    Bien vu ;-) Bon par contre, je ne sais pas ce qu'il se passe mais on avance.
    Merci pour l'aide déjà apportée.

  8. #8
    Membre averti

    Inscrit en
    Juin 2008
    Messages
    307
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 307
    Points : 364
    Points
    364
    Par défaut
    Il passe quoi comme requête pour trouver l'entité (notamment le paramètre) ? et si tu l’exécute manuellement ca donne quoi ?

  9. #9
    Membre du Club
    Femme Profil pro
    Inscrit en
    Avril 2011
    Messages
    127
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2011
    Messages : 127
    Points : 49
    Points
    49
    Par défaut
    En fait, je suis certaine que le problème se situe au niveau du form->isValid().

    Si je passe la souris sur un lien, on est ok: je dois avoir la route et le paramètre passé.
    Ben si je passe ma souris sur le bouton "supprimer", je n'ai ni route ni paramètre. J'ai juste... rien lol.

    Du coup, j'ai fa ç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
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
     
    public function deleteAction(Request $request, $id)
        {
            $form = $this->createDeleteForm($id);
            $form->submit($request);
     
            if ($form->isValid()) {
                $em = $this->getDoctrine()->getManager();
                $entity = $em->getRepository('SiteFrontBundle:Comment')->find($id);
     
                if (!$entity) {
                    throw $this->createNotFoundException('Unable to find Comment entity.');
                }
     
                $em->remove($entity);
                $em->flush();
            }
            else{
                var_dump($form->getErrorsAsString());
                exit;
            }
     
     
            return $this->redirect($this->generateUrl('admin_comment'));
        }
    et j'ai ceci:
    string 'ERROR: Le jeton CSRF est invalide. Veuillez renvoyer le formulaire.
    ' (length=68)


    D'ailleurs, si je fais:

    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
     
    public function deleteAction(Request $request, $id)
        {
            $form = $this->createDeleteForm($id);
            $form->submit($request);
     
                $em = $this->getDoctrine()->getManager();
                $entity = $em->getRepository('SiteFrontBundle:Comment')->find($id);
     
                if (!$entity) {
                    throw $this->createNotFoundException('Unable to find Comment entity.');
                }
     
                $em->remove($entity);
                $em->flush();
     
     
     
            return $this->redirect($this->generateUrl('admin_comment'));
        }
    Tout fonctionne. Sauf que question sécurité c'est pas top.. Et je ne peux pas me permettre cela sur un travail de fin d'étude.

    Donc j'ai fait des recherches, j'ai capté qu'il faudrait ajouter le champ CSRF, dans la doc ils en parlent: http://symfony.com/fr/doc/current/co...arameters.html

    Mais si j'ajoute le CSRF via
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    {{ form_widget(form) }}
    , j'ai une erreur Variable "form" does not exist
    Pareil si je fait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     {{ form_widget(delete_form) }}
    Idem si j'ajoute jeton "à la main" en faisant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}">

  10. #10
    Membre expérimenté Avatar de Nico_F
    Homme Profil pro
    Développeur Web
    Inscrit en
    Avril 2011
    Messages
    728
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Avril 2011
    Messages : 728
    Points : 1 310
    Points
    1 310
    Par défaut
    La méthode GET n'est pas faite pour supprimer des données, et l'utiliser comme tel présente des failles de sécurité. N'importe qui peut supprimer une entité juste en passant la bonne URL.

    D'autre part, c'est bien beau de faire un formulaire de suppression dans ton contrôleur mais il faudrait peut-être le passer à ta template pour l'afficher. Le message 'Variable "form" does not exist' aurait du te mettre la puce à l'oreille. La méthode de ce formulaire doit être DELETE.

    Pour finir, si ton problème c'est que ton bouton de formulaire doit avoir l'air d'être un lien, c'est en CSS que l'on gère ce genre de chose.
    => http://jsfiddle.net/adardesign/5vHGc/

    ++

  11. #11
    Membre du Club
    Femme Profil pro
    Inscrit en
    Avril 2011
    Messages
    127
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2011
    Messages : 127
    Points : 49
    Points
    49
    Par défaut
    Merci de répondre ;-)

    Bon, je t'avoue, je suis sur ce souci depuis quelque jours, et avec toutes ces modifications.. Je commence à me perdre.
    Cela dit, comme expliqué plus haut dans la conversation, je ne suis pas en GET (sauf erreur de ma part):

    Ma route:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    admin_comment_delete:
        path:     /{id}/delete
        defaults: { _controller: "SiteFrontBundle:Admin/Comment:delete" }
        requirements: { _method: post|delete }

    Mon form:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    <form action="{{ path('admin_comment_delete', { 'id': entity.id }) }}" method="post">
        <input type="hidden" name="_method" value="DELETE" />
        <button type="submit">Delete</button>
    </form>
    Formulaire en post, et méthode en post/delete => pas de GET, si ?

    Pour ce qui est du passage du formulaire au template.. Je t'avoue ne pas comprendre, puisque le form est dans ma page index

    Désolée hein, mais je trouve cela bien compliqué... J'dois pas être la seule à vouloir un admin, qui rend des tableaux, avec pour chaque ligne différentes données, et les actions show, edit et delete, comme ceci:

  12. #12
    Membre expérimenté Avatar de Nico_F
    Homme Profil pro
    Développeur Web
    Inscrit en
    Avril 2011
    Messages
    728
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Avril 2011
    Messages : 728
    Points : 1 310
    Points
    1 310
    Par défaut
    Si tu veux afficher ton formulaire de suppression dans ta page index il faut que tu commences par créer un formulaire de suppression dans ton action index.
    Ensuite tu l'afficheras normalement via {{ form_widget(delete_form) }}.

    La méthode de ton formulaire devrait être DELETE plutôt que POST, mais ça c'est du détail.

  13. #13
    Membre du Club
    Femme Profil pro
    Inscrit en
    Avril 2011
    Messages
    127
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2011
    Messages : 127
    Points : 49
    Points
    49
    Par défaut
    Ok, c'est ce que je suis en train de tester.

    Voici l'action index:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    public function indexAction()
        {
            $em = $this->getDoctrine()->getManager();
     
            $entities = $em->getRepository('SiteFrontBundle:Comment')->findAll();
     
            return $this->render('SiteFrontBundle:Admin/Comment:index.html.twig', array(
                'entities' => $entities,
            ));
        }
    Le souci, c'est que dans l'index je n'ai pas l'id. Hors, pour déclarer mon formulaire dans l'action, j'en ai besoin...

    Par exemple, dans show (qui intègre le deleteForm), j'ai ceci:

    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
     
    public function showAction($id)
        {
            $em = $this->getDoctrine()->getManager();
     
            $entity = $em->getRepository('SiteFrontBundle:Comment')->find($id);
     
            if (!$entity) {
                throw $this->createNotFoundException('Unable to find Comment entity.');
            }
     
            $deleteForm = $this->createDeleteForm($id);
     
            return $this->render('SiteFrontBundle:Admin/Comment:show.html.twig', 
                    array(
                        'entity'      => $entity,
                        'delete_form' => $deleteForm->createView(),
            ));
        }
    Si j'essaye ça sur index, j'ai une erreur:
    CommentController::indexAction()" requires that you provide a value for the "$id" argument

    Je te remercie de m'aider en tout cas ;-)

  14. #14
    Membre expérimenté Avatar de Nico_F
    Homme Profil pro
    Développeur Web
    Inscrit en
    Avril 2011
    Messages
    728
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Avril 2011
    Messages : 728
    Points : 1 310
    Points
    1 310
    Par défaut
    Alors je vais revenir sur ce que j'ai dit tout à l'heure : autorise la méthode GET et DELETE pour ton contrôleur deleteAction.

    Ton contrôleur deleteAction fera deux choses :
    • il affichera une page de confirmation du type "êtes vous sûr de vouloir supprimer ce commentaire ?" lorsque tu y accèdes en GET. Il affichera également le formulaire de suppression (méthode DELETE), basé sur l'ID que tu lui auras passé en URL.
    • il supprimera le commentaire en question lorsque tu y accèdes en DELETE et te redirigera vers la page de ton choix.


    De cette manière tu peux tranquillement faire un lien vers la route 'admin_comment_delete', en passant l'id de chaque commentaire en paramètre.
    Et une fois que tu es sur la page tu affiches le formulaire de suppression dont la cible est la même route. La seule différence sera la méthode utilisée, tu gères ça dans ton contrôleur deleteAction et c'est bouclé.

    ++

  15. #15
    Membre du Club
    Femme Profil pro
    Inscrit en
    Avril 2011
    Messages
    127
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2011
    Messages : 127
    Points : 49
    Points
    49
    Par défaut
    OK, je vais essayer de mettre cela en place, mais je sais déjà que je vais galérer.. lol

  16. #16
    Membre averti

    Inscrit en
    Juin 2008
    Messages
    307
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 307
    Points : 364
    Points
    364
    Par défaut
    Citation Envoyé par Nico_F Voir le message
    La méthode GET n'est pas faite pour supprimer des données, et l'utiliser comme tel présente des failles de sécurité. N'importe qui peut supprimer une entité juste en passant la bonne URL.
    Je tempérerai cette affirmation car a priori c'est dans un backend sécurisé. Mais c'est sur c'est plus propre.

Discussions similaires

  1. [Mail] Ajout d'un lien dans un scipt formmail.php
    Par PaulK dans le forum Langage
    Réponses: 1
    Dernier message: 13/11/2007, 22h59
  2. [XML] ajout d'un lien dans un document
    Par caroy dans le forum Flash
    Réponses: 4
    Dernier message: 12/03/2007, 01h26
  3. Ajouter la contrainte ON DELETE SET NULL a postériori
    Par EvilAngel dans le forum SQL Procédural
    Réponses: 2
    Dernier message: 24/09/2006, 11h36

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