简体   繁体   English

Symfony 3.4 无法在生产环境中删除

[英]Symfony 3.4 can't delete in production env

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 .我有一个 Symfony 应用程序,在我的本地和临时服务器上的 dev env 中运行良好,因此使用app_dev.php When I test the same application on my staging server in prod mod (so with app.php or just http://servername/ delete forms does't work. I have errors in my log : Request.ERROR: Uncaught PHP Exception Symfony\\Component\\HttpKernel\\Exception\\MethodNotAllowedHttpException: "No route found for "POST /fr/invitesgroupe/3024": Method Not Allowed (Allow: DELETE)"当我在 prod mod 的临时服务器上测试相同的应用程序时(所以使用app.php或只是http://servername/删除表单不起作用。我的日志中有错误: Request.ERROR: Uncaught PHP Exception Symfony\\Component\\HttpKernel\\Exception\\MethodNotAllowedHttpException: "No route found for "POST /fr/invitesgroupe/3024": Method Not Allowed (Allow: DELETE)"

I generated this part with CRUD generator: Controller :我用 CRUD 生成器生成了这部分:控制器:

namespace AppBundle\Controller;

use AppBundle\Entity\InvitesGroupe;
use AppBundle\Entity\Reservations;
use AppBundle\Form\InvitesGroupeType;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

/**
 * 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('AppBundle\Form\InvitesGroupeType', $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('AppBundle\Form\InvitesGroupeType', $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.我在 plesk Onyx 17.8.11,php 5.6.36 上。 Thanks for your help谢谢你的帮助

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". 您的请求方法是POST,但是在路由声明“ / fr / invitesgroupe / 3024”之后,由deleteAction()处理,并且唯一允许的方法是“ DELETE”。 So "POST /fr/invitesgroupe/3024" should be "DELETE /fr/invitesgroupe/3024". 因此,“ POST / fr / invitesgroupe / 3024”应为“ DELETE / fr / invitesgroupe / 3024”。

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.首先,一些背景知识:Symfony 表单在删除对象时实际上并没有使用真正的 HTTP DELETE 方法。 Instead, they send a POST request with a hidden attribute, _method , set to DELETE.相反,他们发送一个带有隐藏属性_method的 POST 请求,设置为 DELETE。 This is because HTML forms only support GET and POST methods.这是因为 HTML 表单仅支持 GET 和 POST 方法。 This is all done behind the scenes for you if you use the Symfony form components.如果您使用 Symfony 表单组件,这一切都是在幕后为您完成的。

To make everything work nicely in the backend, the Symfony framework has an option called http_method_override , which is enabled by default.为了让后端的一切都很好地工作,Symfony 框架有一个名为http_method_override的选项,默认情况下是启用的。 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 ._method POST 请求发送的_method转换为看起来像真正的 DELETE 请求的 Symfony 路由器,因此您可以将您的路由标记为处理 DELETE,并且当表单实际向它发送带有_method: DELETE的 POST 时,一切正常。

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.我猜你会像我一样使用Symfony Reverse Proxy ,它在开发环境中被禁用并在生产中启用。

In the recommended default configuration , the Symfony Reverse Proxy will ignore the _method parameter.推荐的默认配置中,Symfony 反向代理将忽略_method参数。 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.这意味着在生产中运行时,请求在路由中显示为 POST 请求而不是 DELETE,从而导致错误。

As you can see , there's a recommendation now to call Request::enableHttpMethodParameterOverride() just after creating the caching Kernel in your index.php .您所见,现在建议在index.php创建缓存内核后立即调用Request::enableHttpMethodParameterOverride() 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.这让反向代理可以将带有_method: DELETE的 POST 解释为路由器的真正 DELETE,这就是我需要做的事情才能使事情适合我的情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM