phpsymfonycookiesroutes

How to use a cookie in routing configuration in Symfony2?


I have a City parameter stored in a cookie. I would like to include its value as a pattern prefix in my routing configuration like so:

# MyBundle/Resources/config/routing.yml

MyBundle_hotel:
    resource: "@MyBundle/Resources/config/routing/hotel.yml"
    prefix:   /%cityNameFromCookie%/hotel

How can I achieve that?


Solution

  • Give us a use case on how you would want this to work because I don't see the difficulty. Routes are made of parameters that you can specify through the generateUrl function, the url twig function or the path twig function.

    In Twig you can do this

    {{ path('MyBundle_hotel', {cityNameFromCookie: app.request.cookies.get('cityNameFromCookie')}) }}
    

    In a controller action

    $cookieValue = $this->get('request')->cookies->get('cityNameFromCookie');
    $url = $this->generateUrl('MyBundle_hotel', array('cityNameFromCookie' => $cookieValue));
    

    Or from any places that have access to the container

    $cookieValue = $this->container->get('request')->cookies->get('cityNameFromCookie');
    $url = $this->container->get('router')->generate('MyBundle_hotel', array('cityNameFromCookie' => $cookieValue));
    

    In the last example, you will probably want to change how the container is being accessed.

    If you are concerned about how complicated it looks like, you can abstract this logic and put it inside a service or extend the router service.

    You can find documentation about services and the service container in the Symfony's documentation.

    You can also list the services via the command php app/console container:debug and will find the router service and its namespace and from this you can try to figure out how to extend the router service (a very good way to learn how services work).

    Otherwise, here is simple way to create a service.

    In your services.yml (either in your Bundle or in app/config/config.yml)

    services:
        city:
            class: MyBundle\Service\CityService
            arguments: [@router, @request]
    

    In your CityService class

    namespace MyBundle\Service
    
    class CityService
    {
    
        protected $router;
        protected $request;
    
        public function __construct($router, $request) 
        {
            $this->router = $router;
            $this->request = $request;
        }
    
        public function generateUrl($routeName, $routeParams, $absoluteUrl)
        {
            $cookieValue = $this->request->cookies->get('cityNameFromCookie');
    
            $routeParams = array_merge($routeParams, array('cityNameFromCookie' => $cookieValue));
    
            return $this->router->generateUrl($routeName, $routeParams, $absoluteUrl);
        }
    }
    

    Anywhere you have access to the container, you will be able to do the following

    $this->container->get('city')->generateUrl('yourroute', $params);
    

    If you still think that it isn't a great solution; you will have to extend the router service (or find a better way to extend the router component to make it behave the way you are expecting it to).

    I personally use the method above so I can pass an entity to a path method in Twig. You can find an example in my MainService class and PathExtension Twig class defined in the services.yml.

    In Twig, I can do forum_path('routename', ForumEntity) and in a container aware environment I can do $this->container->get('cornichon.forum')->forumPath('routename', ForumEntity).

    You should have enough information to make an informed decision