phpsymfonycontrollerannotationshttp-protocols

How to use multiple method annotations on specific routes?


I know that there are discussions of what are the best practices for handling routes in Symfony2 (routing.yml vs annotations). Just let me mention, that I want to keep the way it is, using annotations.

When I define multiple routes for a single action in a controller, it seems, that the last definition of @Method annotations overrides all the other and thats why I'm getting the following error:

No route found for "POST /index": Method Not Allowed (Allow: GET, HEAD)

This is just a short snippet of code I'm using.

namespace MySelf\MyBundle\Controller;

use Symfony\Component\HttpFoundation\Response;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;

class MyController extends Controller{

    /**
     * @Route(
     *     "/index",
     *     name="index_default"
     * )
     * @Method({"GET", "POST"})
     *
     * @Route(
     *     "/index/{id}",
     *     name="index",
     *     requirements={
     *          "id": "\d+"
     *     }
     * )
     * @Method({"GET"})
     *
     * @return Response
     */
     public function indexAction($id = null){
          /*DO SOME FANCY STUFF*/
          ...
          return $response;
     }
}

whilest this is working very well!

index_default:
    pattern: /index
    defaults: { _controller: MyBundle:MyController:index }
    requirements:
      _method: GET|POST

index:
    pattern: /index/{id}
    defaults: { _controller: MyBundle:MyController:index }
    requirements:
      _method: GET
      id: \d+

Any idea to implement it the way it is working with routing.yml using annotations instead?


Solution

  • You should specify the methods in each route annotation, @Method must be declared only once. In fact each type of annotation are handled separately, they are not aware of each others.

    /**
     * @Route(
     *     "/index",
     *     name="index_default",
     *     methods="GET|POST"
     * )
     *
     * @Route(
     *     "/index/{id}",
     *     name="index",
     *     requirements={
     *          "id": "\d+"
     *     },
     *     methods="GET"
     * )
     *
     * @return Response
     */