skip to Main Content

I have an error that I can’t resolve.
I have a Symfony application, running well in dev env on my local and on the staging server, so with app_dev.php.
When I test the same application on my staging server in prod mod (so with app.phpor just http://servername/ delete forms does’t work. I have errors in my log : Request.ERROR: Uncaught PHP Exception SymfonyComponentHttpKernelExceptionMethodNotAllowedHttpException: "No route found for "POST /fr/invitesgroupe/3024": Method Not Allowed (Allow: DELETE)"

I generated this part with CRUD generator:
Controller :

namespace AppBundleController;

use AppBundleEntityInvitesGroupe;
use AppBundleEntityReservations;
use AppBundleFormInvitesGroupeType;
use SensioBundleFrameworkExtraBundleConfigurationMethod;
use SensioBundleFrameworkExtraBundleConfigurationRoute;
use SymfonyBundleFrameworkBundleControllerController;
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentHttpFoundationResponse;

/**
 * InvitesGroupe controller.
 *
 * @Route("/invitesgroupe")
 */
class InvitesGroupeController extends Controller
{
    /**
     * Lists all InvitesGroupe entities.
     *
     * @Route("/", name="invitesgroupe_index")
     * @Method("GET")
     */
    public function indexAction(Request $request)
    {

        $em = $this->getDoctrine()->getManager();

        $day = $request->get('day');
        $resto = $request->get('resto');

        $user = !$this->get('security.authorization_checker')
            ->isGranted('ROLE_SUPERVISEUR') ? "AND ig.user = '".$this->getUser()->getId()."'" : "";

        if ($day) {
            $day = DateTime::createFromFormat('d/m/Y', $day);
            $dql   = "SELECT ig FROM AppBundle:InvitesGroupe ig 
                    LEFT JOIN AppBundle:Reservations r WITH r.idInvite = ig.idInvite
                    WHERE ig.inviteVisible = 1
                    AND ig.inviteTemporaire IS NULL
                    AND r.date = '".$day->format('Y-m-d')."'
                    ".$user."
                    ORDER BY ig.idInvite DESC";
        } elseif ($resto && $day) {
            $day = DateTime::createFromFormat('d/m/Y', $day);
            $dql   = "SELECT ig FROM AppBundle:InvitesGroupe ig 
                    LEFT JOIN AppBundle:Reservations r WITH r.idInvite = ig.idInvite
                    WHERE ig.inviteVisible = 1 AND ig.inviteTemporaire IS NULL
                    AND r.idRestaurant = ".$resto."
                    AND r.date = '".$day->format('Y-m-d')."'
                    ".$user."
                    ORDER BY ig.idInvite DESC";

        } else {
            $dql   = "SELECT ig FROM AppBundle:InvitesGroupe ig
                    LEFT JOIN AppBundle:Reservations r WITH r.idInvite = ig.idInvite
                    WHERE ig.inviteVisible = 1 AND ig.inviteTemporaire IS NULL
                    AND r.date >= CURRENT_TIMESTAMP()
                    ".$user."
                    ORDER BY ig.idInvite DESC";
        }

        $query = $em->createQuery($dql);


        $paginator  = $this->get('knp_paginator');
        $pagination = $paginator->paginate(
            $query, /* query NOT result */
            $request->query->getInt('page', 1)/*page number*/,
            10/*limit per page*/
        );

        $deleteForms = array();

        if (null !== $request->get('print')) {
            return $pagination;
        }

        foreach ($pagination as $page) {
            $deleteForms[$page->getIdInvite()] = $this->createDeleteForm($page)->createView();
        }

        if ($day) {
            $restoTest = array();
            $restos = array();
            foreach ($pagination as $invite) {
                if (!in_array($invite->getIdService()->getIdRestaurant()->getIdRestaurant(), $restoTest)) {
                    $obj = new stdClass();
                    $obj->id = $invite->getIdService()->getIdRestaurant()->getIdRestaurant();
                    $obj->nom = $invite->getIdService()->getIdRestaurant()->getNomRestaurant();
                    $restos[] = $obj;
                    $restoTest[] = $invite->getIdService()->getIdRestaurant()->getIdRestaurant();

                }
            }
        }



        return $this->render('invitesgroupe/index.html.twig', array(
            'invitesGroupes' =>  $pagination,
            'delete_forms' => $deleteForms,
            'day'  => $day ? $day : null,
            'restos' => isset($restos) ? json_encode($restos) : null
        ));
    }

    /**
     * Creates a new InvitesGroupe entity.
     *
     * @Route("/new", name="invitesgroupe_new")
     * @Method({"GET", "POST"})
     */
    public function newAction(Request $request)
    {
        $invitesGroupe = new InvitesGroupe();
        $reservation = new Reservations();
        $invitesGroupe->addReservation($reservation);
        $invitesGroupe->setUser($this->getUser());
        $form = $this->createForm('AppBundleFormInvitesGroupeType', $invitesGroupe);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $em = $this->getDoctrine()->getManager();
//            $coutRepas = $em->getRepository('AppBundle:CoutsRepas')->coutParDefaut();
            // récupération des dates dans datepicker
            $datePicker = $form['datepicker']->getData();
            $datePicker = explode(',', $datePicker);

            $dates = array();

            foreach ($datePicker as $dt) {
                $dates[] = DateTime::createFromFormat('d/m/Y', $dt);
            }

            $first = true;
            /*
             * First reservation is in the form
             */

            if (!$form->getViewData()->getReservations()[0]->getIdService()) {
                $service = $em->getRepository('AppBundle:Services')
                    ->findOneBy(
                        array(
                            'idRestaurant' => $form->getViewData()->getReservations()[0]->getIdRestaurant(),
                            'serviceResa' => 1
                        )
                    );
                $form->getViewData()->getReservations()[0]->setIdService($service);
            } else {
                $service = $form->getViewData()->getReservations()[0]->getIdService();
            }

            $invitesGroupe->setIdService($service);
            if (null === $form->getViewData()->getUser()) {
                $invitesGroupe->setUser($this->getUser());
            }

            foreach ($dates as $date) {
                if ($first) {
                    $reservation = $form->getViewData()->getReservations()[0];

                    $invitesGroupe->setNombre($reservation->getNbPlace());

                    $reservation->setDate($date)
                        ->setIdRestaurant($form->getViewData()->getReservations()[0]->getIdRestaurant())
                        ->setIdService($service)
                        ->setNbPlace($invitesGroupe->getNombre())
//                        ->setCoutTotal($reservation->getNbPlace() * $coutRepas->getCout())
                    ;

                    $invitesGroupe->setNombre($reservation->getNbPlace());
                    $first = false;
                } else {
                    $reservation = new Reservations();
                    $reservation->setDate($date)
                        ->setIdRestaurant($form->getViewData()->getReservations()[0]->getIdRestaurant())
                        ->setIdService($service)
                        ->setNbPlace($invitesGroupe->getNombre())
//                        ->setCoutTotal($reservation->getNbPlace() * $coutRepas->getCout())
                        ->setRepasCompris($reservation->getRepasCompris())
                    ;
                }

                $invitesGroupe->addReservation($reservation);
                $reservation->setInvitesGroupes($invitesGroupe);

                $em->persist($reservation);
                // $em->flush();


            }

            $em->persist($invitesGroupe);
            $em->flush();


            // sending confirmation mail

            $message = Swift_Message::newInstance()
                ->setSubject('['.$form->getViewData()
                        ->getReservations()[0]->getIdRestaurant()
                        ->getNomRestaurant().'] Réservation prise en compte')
                ->setFrom('')
                ->setTo($invitesGroupe->getUser()->getEmail())
                ->setBody(
                    $this->renderView(
                    // app/Resources/views/emails/invitegroupe.html.twig
                        'emails/invitegroupe.html.twig',
                        array('invite' => $invitesGroupe,
                            'modif' => false,
                            'temp' => false)
                    ),
                    'text/html'
                )
            ;
            $this->get('mailer')->send($message);

            return $this->redirectToRoute('invitesgroupe_index');
        }

        return $this->render('invitesgroupe/new.html.twig', array(
            'invitesGroupe' => $invitesGroupe,
            'form' => $form->createView(),
        ));
    }


    /**
     * Print pdf of the day selected.
     *
     * @Route("/print", name="invitesgroupe_print")
     * @Method("GET")
     */
    public function printAction(Request $request)
    {

        $invites = $this->indexAction($request);

        $services = array();
        foreach ($invites as $invite) {
            if (!in_array($invite->getIdService(), $services) && $invite->getIdService()
                    ->getIdRestaurant()->getIdRestaurant() == $request->get('resto')) {
                $services[] = $invite->getIdService();
            }
        }

        $day = DateTime::createFromFormat('d/m/Y', $request->get('day'));

        // on stocke la vue à convertir en PDF,
        // en n'oubliant pas les paramètres twig si la vue comporte des données dynamiques
        $html = $this->render('pdf/invitation.html.twig', array('invites' => $invites,
            'day' => $day,
            'resto' => $request->get('resto'),
            'services' => $services
        ));
        //on appelle le service html2pdf
        $html2pdf = $this->get('html2pdf_factory')->create();
        //real : utilise la taille réelle
        $html2pdf->pdf->SetDisplayMode('real');
        // $html2pdf->setModeDebug();
        //writeHTML va tout simplement prendre la vue stocker dans la variable $html pour la convertir en format PDF
        $html2pdf->writeHTML($html);
        //Output envoit le document PDF au navigateur internet
        return new Response($html2pdf->Output('invitation-du'.$day->format('d-m-Y').'.pdf'),
            200, array('Content-Type' => 'application/pdf')
        );
    }

    /**
     * Print pdf of the day selected.
     *
     * @Route("/see", name="invitesgroupe_see")
     * @Method("GET")
     */
    public function seeAction(Request $request) {

        $invites = $this->indexAction($request);

        $services = array();
        foreach ($invites as $invite) {
            if (!in_array($invite->getIdService(), $services) && $invite->getIdService()
                    ->getIdRestaurant()->getIdRestaurant() == $request->get('resto')) {
                $services[] = $invite->getIdService();
            }
        }

        $day = DateTime::createFromFormat('d/m/Y', $request->get('day'));

        return $this->render('pdf/invitation.html.twig', array('invites' => $invites,
            'day' => $day,
            'resto' => $request->get('resto'),
            'services' => $services
        ));
    }

    /**
     * Displays a form to edit an existing InvitesGroupe entity.
     *
     * @Route("/{id}/edit", name="invitesgroupe_edit")
     * @Method({"GET", "POST"})
     */
    public function editAction(Request $request, InvitesGroupe $invitesGroupe)
    {
        $deleteForm = $this->createDeleteForm($invitesGroupe);
        $editForm = $this->createForm('AppBundleFormInvitesGroupeType', $invitesGroupe);
        $editForm->handleRequest($request);
        if ($editForm->isSubmitted() && $editForm->isValid()) {
            $em = $this->getDoctrine()->getManager();
            /**
             * @Doc : retrieve dates from field datepicker
             */
            $datePicker = $editForm['datepicker']->getData();
            $datePicker = explode(',', $datePicker);
            $dates = array();
            foreach ($datePicker as $dt) {
                $dates[] = DateTime::createFromFormat('d/m/Y', $dt);
            }

            $data = $editForm->getViewData();
            $postedReservation = $data->getReservations()[0];

            // changement de restaurant et de service
            $restaurant = $postedReservation->getIdRestaurant() !== null ?
                $postedReservation->getIdRestaurant() :
                $invitesGroupe->getIdService()->getIdRestaurant();

            if ($postedReservation->getIdService() !== $invitesGroupe->getIdService()) {
                $invitesGroupe->setIdService($postedReservation->getIdService());
            }

//            $coutRepas = $em->getRepository('AppBundle:CoutsRepas')->coutParDefaut();

            /**
             * @doc : check if one date has been removed
             */

            $invitesGroupe->setNombre($data->getReservations()[0]->getNbPlace());

            $checkDates = $reservation= $em->getRepository('AppBundle:Reservations')
                ->findByIdInvite($invitesGroupe->getIdInvite());

            foreach ($checkDates as $checkDate) {
                if (!in_array($checkDate, $dates)) {
                    // date removed
                    $invitesGroupe->removeReservation($checkDate);
                    $em->remove($checkDate);
                    $em->persist($invitesGroupe);
                    $em->flush();
                }
            }

            if (null === $editForm->getViewData()->getUser()) {
                $invitesGroupe->setUser($this->getUser());
            }

            foreach ($dates as $date) {

                /**
                 * @doc : dates is new ?
                 */
                $reservation= $em->getRepository('AppBundle:Reservations')
                    ->findBy(array('idInvite' => $invitesGroupe->getIdInvite(), 'date' => $date));

                if (!$reservation) {
                    /* yes */
                    $reservation = new Reservations();
                    $reservation->setDate($date)
                        ->setIdRestaurant($restaurant)
                        ->setIdService($invitesGroupe->getIdService())
                        ->setNbPlace($invitesGroupe->getNombre())
//                        ->setCoutTotal($invitesGroupe->getNombre() * $coutRepas->getCout())
                        ->setRepasCompris($invitesGroupe->getRepasOffert())
                    ;

                    $invitesGroupe->addReservation($reservation);
                    $reservation->setInvitesGroupes($invitesGroupe);

                    $em->persist($reservation);

                }

            }

            $em->persist($invitesGroupe);
            $em->flush();

            // sending confirmation mail

            $message = Swift_Message::newInstance()
                ->setSubject('['.$restaurant->getNomRestaurant().'] Réservation modifiée')
                ->setFrom('')
                ->setTo($invitesGroupe->getUser()->getEmail())
                ->setBody(
                    $this->renderView(
                    // app/Resources/views/emails/invitegroupe.html.twig
                        'emails/invitegroupe.html.twig',
                        array('invite' => $invitesGroupe,
                            'restaurant' => $restaurant,
                            'modif' => true,
                            'temp' => false)
                    ),
                    'text/html'
                )
            ;
            $this->get('mailer')->send($message);

            return $this->redirectToRoute('invitesgroupe_index');
        }

        return $this->render('invitesgroupe/edit.html.twig', array(
            'invitesGroupe' => $invitesGroupe,
            'edit_form' => $editForm->createView(),
            'delete_form' => $deleteForm->createView(),
        ));
    }

    /**
     * Deletes a InvitesGroupe entity.
     *
     * @Route("/{id}", name="invitesgroupe_delete")
     * @Method("DELETE")
     */
    public function deleteAction(Request $request, InvitesGroupe $invitesGroupe)
    {
        $form = $this->createDeleteForm($invitesGroupe);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid() &&
            $this->get('security.authorization_checker')->isGranted('ROLE_SUPERVISEUR')
        ) {
            $em = $this->getDoctrine()->getManager();
            $em->remove($invitesGroupe);
            $em->flush();

            // sending confirmation mail

            if ($invitesGroupe->getUser() !== $this->getUser()) {
                $restaurant = $em->getRepository('AppBundle:Restaurants')
                    ->findOneByIdRestaurant($invitesGroupe->getIdService()->getIdRestaurant());

                $message = Swift_Message::newInstance()
                    ->setSubject('['.$restaurant->getNomRestaurant().'] Réservation annulée')
                    ->setFrom('')
                    ->setPriority(1)
                    ->setTo($invitesGroupe->getUser()->getEmail())
                    ->setBody(
                        $this->renderView(
                        // app/Resources/views/emails/invitegroupe_canceled.html.twig
                            'emails/invitegroupe.html.twig',
                            array('invite' => $invitesGroupe,
                                'restaurant' => $restaurant,
                                'delete' => true,
                                'temp' => false,
                                'modif' => true
                            )
                        ),
                        'text/html'
                    )
                ;
                $this->get('mailer')->send($message);
            }

        }

        return $this->redirectToRoute('invitesgroupe_index');
    }

    /**
     * Creates a form to delete a InvitesGroupe entity.
     *
     * @param InvitesGroupe $invitesGroupe The InvitesGroupe entity
     *
     * @return mixed
     */
    private function createDeleteForm(InvitesGroupe $invitesGroupe)
    {
        return $this->createFormBuilder()
            ->setAction($this->generateUrl('invitesgroupe_delete', array('id' => $invitesGroupe->getIdInvite())))
            ->setMethod('DELETE')
            ->getForm()
            ;
    }
}

I’m on plesk Onyx 17.8.11, php 5.6.36.
Thanks for your help

2

Answers


  1. Your request method is POST but following your route declaration “/fr/invitesgroupe/3024” is handled by the deleteAction() and there the only allowed method is “DELETE”. So
    “POST /fr/invitesgroupe/3024” should be “DELETE /fr/invitesgroupe/3024”.

    Login or Signup to reply.
  2. I realise this is a rather old question, but I just had the same problem, and I may be able to explain.

    First, a bit of background: Symfony forms don’t actually use a real HTTP DELETE method when deleting an object. Instead, they send a POST request with a hidden attribute, _method, set to DELETE. This is because HTML forms only support GET and POST methods. This is all done behind the scenes for you if you use the Symfony form components.

    To make everything work nicely in the backend, the Symfony framework has an option called http_method_override, which is enabled by default. This translates the _method sent by a POST request into something that looks to the Symfony router like a genuine DELETE request, so you can mark your route as handling a DELETE and everything works when the form actually sends it a POST with _method: DELETE.

    My guess would be that like me you were using the Symfony Reverse Proxy, with it disabled in the dev environment and enabled in production.

    In the recommended default configuration, the Symfony Reverse Proxy will ignore the _method parameter. This means that when running in production, the request appears to the routing as a POST request rather than a DELETE, leading to the error.

    As you can see, there’s a recommendation now to call Request::enableHttpMethodParameterOverride() just after creating the caching Kernel in your index.php. This lets the reverse proxy interpret the POST with _method: DELETE as a real DELETE for the router, and is all I needed to do to get things working for my situation.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search