Meena Alfons
Meena Alfons

Reputation: 1230

Two Routes for one Controller OR Two Routes for a group of actions

Here is the scheme of the required URLs:

/service/getBalance    should map to CustomerController::getBalance
/service/addBalance    should map to CustomerController::addBalance

/customer/getBalance    should map to CustomerController::getBalance
/customer/addBalance    should map to CustomerController::addBalance

Here is a simple controller

<?php

namespace AppBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;

class CustomerController extends Controller {

    /**
     * @Route("/getBalance")
     */
    public function getBalanceAction(Request $request) {

    }

    /**
     * @Route("/addBalance")
     */
    public function addBalanceAction(Request $request) {

    }

} // class CustomerController

Have tried the following ways. None of them worked.

# rounting.yml
v1:
    resource: "@AppBundle/Controller/CustomerController.php"
    prefix:   /service
    type:     annotation

v2:
    resource: "@AppBundle/Controller/CustomerController.php"
    prefix:   /customer
    type:     annotation

loading the same resource with different prefix always overrides the previous occurrence (the last one works). The following also doesn't work for the same reason and have the same behavior.

# rounting.yml
v1:
    resource: "@AppBundle/Resources/config/routing_customer.yml"
    prefix:   /service

v2:
    resource: "@AppBundle/Resources/config/routing_customer.yml"
    prefix:   /customer


# routing_customer.yml
getBalance:
    path: /getBalance
    defaults : { _controller: "AppBundle:Customer:getBalance" }

addBalance:
    path: /addBalance
    defaults : { _controller: "AppBundle:Customer:addBalance" }

Third not working option:

# rounting.yml
v1:
    resource: "@AppBundle/Resources/config/routing_v1.yml"
    prefix:   /     # evenr putting /service here instead of inside

v2:
    resource: "@AppBundle/Resources/config/routing_v2.yml"
    prefix:   /     # evenr putting /customer here instead of inside

# routing_v1.yml
getBalance:
    path: /service/getBalance
    defaults : { _controller: "AppBundle:Customer:getBalance" }

addBalance:
    path: /service/addBalance
    defaults : { _controller: "AppBundle:Customer:addBalance" }

# routing_v2.yml
getBalance:
    path: /customer/getBalance
    defaults : { _controller: "AppBundle:Customer:getBalance" }

addBalance:
    path: /customer/addBalance
    defaults : { _controller: "AppBundle:Customer:addBalance" }

I actually need to route / and /customer to the same controller: /getBalance and /customer/getBalance.

I want to give two prefixes for a group of methods. How to do that in Symfony?

Conclusion from my trials, @goto's answer and @Cerad's comments:

The last Example above could have worked if I used different route names. Route names are unique though out the whole project (Not just unique in file). v1_getBalance and v2_getBalance.

The other solution is to use a custom loader as @goto described.

Upvotes: 2

Views: 4973

Answers (1)

goto
goto

Reputation: 8162

You could do routes this way:

     @Route(
          "/{subject}/getBalance",
          requirements={
              "subject": "customer|service"
          }
      )

in yml:

subject_getbalance:
  path:     /{subject}/getBalance
  requirements:
      subject:  customer|service

The requirement is safer than nothing: it allows you to route another route like foo/getBalance on another controller (as it does not match the requirement)

EDIT: for your special case, as you need /getBalance to map to your route too you could do:

subject_getbalance:
      path:     /{subject}/getBalance
      default: { _controller: YourBundle:Controller }
      requirements:
          subject:  customer|service
default_getbalance:
      path:     /getBalance
      default: { _controller: YourBundle:Controller, subject: customer }

Edit: the last idea is to a custom route loader (but I've never tried):

class ExtraLoader extends Loader
{
    public function load($resource, $type = null)
    {

       /* ... */

        $prefixes = [ 'default_' =>'','customer_' =>'/customer','service_' =>'/service']

        // prepare a new route
        $path = '/getbalance/{parameter}';
        $defaults = array(
            '_controller' => 'YourBundle:Actiona',
        );
        $requirements = array(
            'parameter' => '\d+',
        );
       foreach($prefixes as $prefixName => $prefixRoute) {
          $route = new Route($prefixRoute . $path, $defaults, $requirements);
          $routes->add($prefixName . 'getBalance', $route);
       }

This will allows you to have 3 routes generated:

default_getBalance: /getBalance
customer_getBalance: /customer/getBalance
service_getBalance: /service/getBalance

Upvotes: 6

Related Questions