Search code examples
phpsymfonyannotationssymfony-routing

Overriding Symfony Controller Methods doesn't work properly


I am trying to create a new controller function in the overridden controller class but it doesn't work as intended.

I have a common bundle where I use it for many clients. When sometimes when a client needs a specific function I creates an override for the common controller in the client bundle.

Here is my code for the common bundle controller.

class FrontController extends Controller
{
   // This is the controller in my common bundle

   /**
    * @Route("/foo/{id}", name="front_view")
    */
   public function viewAction(
       string $id,
       Request $request
   ){
       // My Controller code
   }
}

Here is my overridden controller code for client bundle.

class ClientFrontController extends FrontController
{
   // I have 2 controller methods in this class

  // First method overrides the FrontController's viewAction method
  // This works fine
  /**
    * @Route("/foo/{id}", name="front_view")
    */
   public function viewAction(
       string $id,
       Request $request
   ){
       // My Controller code
   }

  //Second method
  //This is the problem
  /**
    * @Route("/foo/bar", name="foo_bar")
    */
   public function fooBarAction(
       Request $request
   ){
       // My Controller code
   }
}

The problem I am facing is that when I navigate to /foo/bar route, it goes to /foo/{id} the overridden method in ClientFrontController.

Why is this happening? How can I make both routes work?


Solution

  • Routes order is relevant.

    /foo/bar is included within /foo/{id}. When evaluating the request, /foo/bar matches /foo/{id} (with id being bar) and since it's declared/read earlier, front_view handles the request.

    If you are on Symfony < 5.1, try moving the routes around (so that foo_bar comes earlier than front_view). Or even changing the routes so that there is no overlap.

    If you are on Symfony 5.1+, you can now use priority on route annotations/attributes. Read the announcement here, and the docs here.

    class ClientFrontController extends FrontController
    {
    
       /**
        * @Route("/foo/{id}", name="front_view")
        */
       public function viewAction(string $id, Request $request)
       {
           // My Controller code
       }
    
       /**
        * @Route("/foo/bar", priority=10, name="foo_bar")
        */
       public function fooBarAction(Request $request)
       {
           // My Controller code
       }
    }