ninjapenguin

Kohana 2.3 Routing

In my last post I mentioned that there’s a change in the works for Kohana 2.3,
and I wasn’t lying! If you watch the forum then you will of certainly seen
some discussions on it, of particular note are:Routing in
2.3
and 2.3 Routing Examples.

I think initially the change was met with skepticism , as these things so
often are, people don’t like future compatibility issues, which is
understandable, but in this case I think the additional advantage gained is
great enough to offset this potential cause of frustration. Hopefully this
post will outline some of those benefits to you, allowing you to make up your
own mind!

Configuration
So the first thing you will notice is that routing is now configured
differently, imo when you get to grips with that is going on then it is
actually now SIMPLER to setup more complex routes, you can now achieve
scenarios with equal or greater flexibility to those of before but without the
use of any regular expressions. The new default route is as follows:

$config[‘default’] Now this may or may not appear self-explanatory, we’ll go through it anyway! Routes are now given a name, this route is called ‘default’, the name itself is not technically important, though we will come to their usage later!
‘:controller/:method/:id’ This is the definition of our routing arguments, prefixing a segment with a colon ‘:’ makes it a router argument, and interpretable as such, :controller and :method are ignored as arguments and if present are used as you would imagine (:controller is used as the request controller, :method for the method)
‘controller’ => ‘welcome’,‘method’ => ‘index’, Here we set the defaults, this basically says that if the controller is not present then use the ‘welcome’ controller and the ‘index’ method within it. If controller is present with no method then use the index method within whichever controller
Play Time Confused? maybe, but with that under our belt we can now start playing around with this. Best way to get to grips with this is to grab a checkout of the development head (http://source.kohanaphp.com/trunk (or http://dev.kohanaphp.com/browser/trunk if your more graphically inclined)) and set yourself up a sandbox! Once installed if you go to your local address you should be presented with the nice new green welcome page.
New Controller Create yourself a new controller ‘Page’ (remember controllers are now defined as ‘class Controller_Page’), and give it an empty index method which echos your favorite hello world substitute before exiting. Going to <your-site>/page will now show you your hello world substitute. This behavior shouldn’t bowl you off your feet, in fact the more astute will probably of noticed that this is exactly the same as with the previous (read current) release!.
Going to <your-site>/page/index will provide the same, <your-
site>/page/index/12 will give the same again (notice the trend), <your-
site>/page/index/12/longWILL BREAK however, this is in contrast to
previous (current) versions in which we could continue to add War and Peace
after the matched route and the framework would continue to hurry us along
without any problem, this gives us MUCH tighter control over our routes and
could potentially provide security benefits (I havn’t worked through that
scenario yet – any input?). It means if we want to capture data then we have
to define it within our route.

If we wanted to capture that fourth segment potentially then we could change
our default route to:

Above we have added another router argument called ‘style’, visiting our
page with 4 segments no longer gives us an error … making any more sense
yet?

Accessing URI parameters (arguments)
So above we have seen how to add additional parameters to the route, how can
we access these named parameters? Router::$arguments is the answer, add to
your index method in your page controller the following, then visit your four
segment route again:

var_dump(router::$arguments['style']);

Very nice. We now have a nice, unified way of accessing these named
parameters.

Practical Example
So lets now run quickly through a practical example to demonstrate some more
of the functionality we can leverage from this . .yes there is more!

Lets re-use our page controller and add a blog_posts function to it. We define
the following route:

The above has introduced the regex functionality, hopefully it is relatively
self-explanatory there. We can basically provide individual regex patterns for
each of our defined url arguments, which makes for some really
nice and simple pattern matching options. Also note how we define our default
year to be the current one, very simple, very effective and very future proof!
All from the routing configuration.

Now visit <your-site>/post and you should see what is going on here! I think
that the set up we’re looking at here is really only scratching the surface of
how versatile and solid the new routing solution will be. Any thoughts?

Reverse Routing
Just to finish this off lets take a look at what really tidies all this up
into a neat package: Reverse routing. This allows us to generate application
links using our configured routes set-up. For instance:

The above will now happily generate the route post/1983/08/22. On its own
not to fantastic, and it came at the price of a slightly longer link
generation syntax. However as some of you are probably realising if we ship
this app over to the states where they do everything backwards ( :) ) we now
want to switch our urls to read ‘post/:year/:day/:month’, so by making that
ONE change in our routes config every single one of our application links
will now match this backwards way of doing things, and because we retrieve our
url arguments by name none of our code will be affected . . truly awsome.
Reorganising methods and controllers is no longer an issue either. Play around
with it and see what you think. Hopefully you will be impressed!

Breath – That turned out to be a bit longer than anticipated so hopefully you got all the way through it, as usual any problems, glaring omissions then please don’t hesitate to drop me a line!
/Matt