symfony routes

Routing rules in symfony are a way of getting simple url’s looking the way you want. So rather than ugly things that show everyone how your system works like:

matthewbull.net/index.php?id=3&detail=false&category=true&year=2008

you can have things like:

matthewbull.net/id/3/detail/false/category/true/year/2008

Even better than that, using symfony’s routing system allows you to completely decouple a url from your code. It allows this because routing is set through a YAML configuration file called routing.yml. So you can change your url in this file without having to worry about its impact on your code, and changing lots of tests for request parameters in your controllers. A simple rule like:

routename:
  url: /*
  param: { module: mymodule, action: myaction }

will magically pair each value to its name, no matter what order those pairs appear in in the url.

Suppose I didn’t want all the request parameters written out in the url above, just their values, or perhaps a slightly more user-friendly parameter name. Something like:

matthewbull.net/3/nodetail/category

This is no problem to do in routing.yml because you can assign alternative names, default values, or no name at all to the values given in the url:

routename:
  url: /:id/nodetail/category
  param: { module: mymodule, action: myaction, detail: false, category: true, year: 2008 }

which will mean the url given above will be interpreted as follows:

first value you put after the domain name will be assumed to be the id

‘nodetail’ in the url actually mean use the parameter detail with value false

category will be true, and year will be 2008 even though no year has been sent (ie 2008 is the default year)

Routing is a great way to get user-friendly urls, generate new urls for the same code, or refactor old urls without having to touch your code. They are perhaps a little tricky to get used to at first, but fairly quickly make sense. The main thing to realise is that rules work from top to bottom, and the first one to match is used. Quite often problems or unexpected results come from not ordering the rules correctly. Always put more general rules lower down!

    • J.J.
    • October 12th, 2008

    Matthew-

    Great post, however I’m still confused about something. You provide the example of:

    url: /:id/nodetail/category
    param: { module: mymodule, action: myaction, detail: false, category: true, year: 2008 }

    as your routing rule, however I don’t see how you can generate that pattern using an internal symfony URL helper like url_for() or link_to(). From what I understand these helpers only accept URIs in the format of ‘module/action’, is there a way around that?

    • matthew
    • October 12th, 2008

    Hi J.J.
    link_to() should be able to take that pattern eg link_to(‘mylink’, ‘@routename?id=1&detail=false&category=true’)

    However I think all this does mean that you’ve got to know something about how the routing rules were constructed to be able to use link_to. ie. it doesn’t seem like you can do something like link_to(‘mylink’, ‘/1/nodetail/category’)

    I suppose this is a somewhat contrived example anyway, because using /nodetail/category in the url isn’t needed – these values default to detail=false and category=true anyway. I just used the example to show how you can allow a url which looks quite different from the underlying request parameters.

  1. No trackbacks yet.