Wednesday, September 14, 2011

Symfony2 - Add subdomain requirement in routing

I was reading a lot about ability to add routing requirement in Symfony2.

Couldn't find any good answer so I tried to write my own.

Basically what we want:

blog.example.com -> goes to some controller
example.com -> goes to different controllers

Solutions is quite simple:

We overwrite class that generates routing cache (even in dev env).

1. In your bundle (or somewhere in project) create routing cache dumper class:

eg. Acme\BlogBundle\Lib\PhpMatcherDumper.php

2. Add your class with overriding compileRoute function

Copy code from: http://pastie.org/2533804
Change namespace and class name

3. Overwrite default class in config.yml

parameters:
    router.options.matcher_dumper_class: Acme\BlogBundle\Lib\PhpMatcherDumper

4. Add requirements in routing
// Acme\BlogBundle\Controller\PostController.php

/**
 * Post controller.
 *
 * @Route(requirements={"_host" = "blog.example.com"})
 */

class PostController extends Controller
{
    /**
     * @Route("/"
)
     * @Template()
     */
    public function indexAction()
    {
        // some code
       
        return array();
    }


    /**
     * @Route("/smth"
, requirements={"_host" = "example.com"})
     * @Template()
     */
    public function someOtherAction()
    {
        // some code
       
        return array();
    }


Other controller:

// Acme\BlogBundle\Controller\DefaultController.php

/**
 * Default controller.
 *
 * @Route(requirements={"_host" = "example.com"})
 */

class DefaultController extends Controller
{

    /**
     * @Route("/"
)
     * @Template()
     */
    public function indexAction()
    {
        // some code
       
        return array();
    }


    /**
     * @Route("/smth"
, requirements={"_host" = "blog.example.com"})
     * @Template()
     */
    public function someOtherAction()
    {
        // some code
       
        return array();
    }


This gives us:
example.comDefaultController:indexAction
blog.example.comBlogController:indexAction
example.com/smthBlogController:someOtherAction
blog.example.com/smthDefaultController:someOtherAction

This should work with all types of routing (yaml, xml, php, annotations).

Why this only works in controllers?
In order to use "_host" in importing routes we would have to change couple of classes that parse, load and create classes from routing files.

~jpass