Using Routes

Once you have setup the Routes to map URLs to your controllers and actions, you will likely want to generate URLs from within your web application.

Horde_Routes_Utils includes two functions for use in your web application that are commonly desired.

  • redirectTo()
  • urlFor()

Both of these functions take a similar set of arguments. The most important being an associative array of keyword arguments that describes the controller, action, and additional variables you'd like present for the URL that's created.

To save you from repeating things, Routes has two mechanisms to reduce the amount of information you need to supply the urlFor() or redirectTo() function.

Named Routes

We saw earlier how the route name ties a set of defaults to a name. We can use this name with our Route functions and its as if we used that set of keyword args:

$m->connect('category_home', 'category/:section', 
  array('controller'=>'blog', 'action'=>'view', 'section'=>'home'));

$utils = $m->utils;

// is equivalent to
$utils->urlFor(array('controller'=>'blog', 'action'=>'view', 'section'=>'home')); 

You can also specify keyword arguments and it will override defaults associated with the route name:

$utils->urlFor('category_home', array('action'=>'index'));

// is equivalent to
$utils->urlFor(controller='blog', action='index', section='home')); 

As you can see, the amount of typing you save yourself by using the route name feature is quite handy.

Using the recently introduced static named routes feature allows you to quickly use common URLs and easily add query arguments:

$m->connect('google_search', '', 
  array('_static' => true));

$utils = $m->utils;
$utils->urlFor('google_search', array('q'=>'routes'));
// will result in

Non-Existent Route Names

If you supply a route name that does not exist, urlFor() will assume that you intend to use the name as the actual URL. It will also prepend it with the proper SCRIPT_NAME if applicable:

# if running underneath a 'mount' point of /myapp will become
# /myapp/css/source.css 

For portable web applications, it's highly encouraged that you use urlFor() for all your URLs, even those that are static resources and images. This will ensure that the URLs are properly handled in various deployment cases.

Route Memory

When your controller and action is matched up from the URL, the variables it set to get there are preserved. This lets you update small bits of the keywords that got you there without specifying the entire thing:

  array('controller'=>'archives', 'action'=>'view', 'year'=>2004,
        'requirements'=>array('year'=>'d{2,4}', 'month'=>'d{1,2}')));

# URL used: /archives/2005/10/4

# Route dict: {'controller': 'archives', 'action': 'view', 'year': '2005',
#              'month': '10', 'day': '4'}

$utils->urlFor(array('day'=>6))                     # =>          /archives/2005/10/6
$utils->urlFor(array('month'=>4))                   # =>          /archives/2005/4/4
$utils->urlFor()                                    # =>          /archives/2005/10/4
$utils->urlFor(array('controller'=>'/archives'))    # =>          /archives 

The route memory is always used for values with the following conditions:

  • If the controller name begins with a /, no values from the Route dict are used
  • If the controller name changes and no action is specified, action will be set to 'index'
  • If you use named routes, no values from the Route dict are used

Overriding Route Memory

Sometimes one doesn't want to have Route Memory present, as well as removing the Implicit Defaults. Routes can disable route memory and implicit defaults either globally, or on a per-route basis. Setting explicit routes:

$m = new Horde_Routes_Mapper(array('explicit'=>true)); 

When toggling explicit behavior for individual routes, only the implicit route defaults will be de-activated. urlFor() behavior can only be set globally with the mapper explicit keyword. Setting explicit behavior for a route:

$m = new Horde_Routes_Mapper();

# Note no 'id' value will be assumed for a default
  array('controller'=>'archives', 'action'=>'view', '_explicit'=>true));

# This will now require an action and id present