Search code examples
phpsymfonyroutesurl-routingsymfony-3.4

Advanced routing in Symfony v3


I'm after a custom routing method so I can have below links to be handled by single controller action:

/q-query_term
/category-category_name/city-city_name/q-query_term
/city-city_name/category-category_name/q-query_term
/city-city_name/q-query_term
/category-category_name/q-query_term
/city-city_name
/category-category_name

Is it possible even possible? I don't use SensioExtraBundle so routes has to be written down in yaml.

For instance in Zend Framework 2 it is possible quite easily, because I can write a class, which would handle the routing as a wish. Don't know how to achieve the same in Symfony though, any help would be appreciated.

The only way I can come up with is to create a custom route loader, calculate all route permutations and return that collection, but don't know if it the best solution possible.

This question is unique, because I need to use single route name instead of specyfing tens of different route definitions.


Solution

  • A simple solution would be to define the route as catch-all …

    # Resources/config/routing.yml
    
    catch_all:
        path:  /{path}
        defaults: { _controller: FooBarBundle:Catchall:dispatcher, path : "" }
        requirements:
            path: ".*"
    

    … and do all further processing in the controller:

    # Controller/CatchallController.php
    
    class CatchallController extends Controller
    {
        public function dispatcherAction(Request $request, string $path)
        {
            if (/* path matches pattern 1 */)
                return $this->doQuery($request, $path);
            elseif (/* path matches pattern 2 */)
                return $this->doCategoryCityQuery($request, $path);
    
            // ... and so on
    
            else
                return new Response("Page not found", 404);
        }
    
        private function doQuery($request, $path)
        {
            // do stuff and return a Response object
        }
    
        private function doCategoryCityQuery($request, $path)
        {
            // do stuff and return a Response object
        }
    }