Router abuse
by Naneau
Routing?
Today a post about Routing, that’s right, a real new post! How to use routes to get from a (nice looking) URL to modules/controllers/actions is something that has been explained in dept here and at other places. This post is not about that. This post is about how to use the router to reverse the process, to build your own pretty urls. For simplicity’s sake I’m going to assume that you use the router to do just that, parse and create URLs. You could of course use it for other funky things, like parsing CLI input.
The router
The router lives in front-controller-land, you have problably retrieved it before, to add routes to it.
1 2 3 | $frontController = Zend_Controller_Front::getInstance(); $router = $frontController->getRouter(); //the router, retrieved from the front controller |
The router holds a collection of routes, that it tries to match against the current request. You can retrieve one of those routes using the getRoute() method. The method getCurrentRouteName() will give you the name of the current route. Remember when you added routes to it you had to give them a name? That is going to come in useful now. If you didn’t add any routes to the router, or aren’t using any special route, the name of the route will be “default”, seeing as how that is… The default.
1 2 3 4 5 | $currentRoute = $router->getCurrentRouteName(); //get the current route name $route = $router->getRoute($currentRoute); //get the actual route object matching the current name |
Assembling routes
While getting a route is fun, it doesn’t do you any good unless you put that route to work. Which is what we’re going to do next! The assemble() method has to be defined by all classes that implement Zend_Controller_Router_Route_Interface (along with the match() method that does the matching of the request). Like it’s name suggests, it is supposed to assemble a url for a given request. It takes an array of parameters as the first param, and an optional boolean as a second, to reset the current request params for assembling.
1 2 3 4 5 6 7 8 9 10 | $params = array( 'module' => 'blog', 'controller' => 'post', 'action' => 'read' 'id' => 13 ); $route = $router->getRoute('default'); $url = $route->assemble($params, true); //create a url using just the params set in $params //this will look like blog/post/read/id/13 |
This is also useful, however, when you don’t use the default route:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
Why do it yourself?
Yes, I am acutely aware that most scenarios for when you’d want to do this are covered. For controllers there’s the redirection action helper, which uses this method to generate it’s urls. For views there’s the url view helper, which helps you generates links to put in your hrefs. But there are places where you don’t have the benefit of these helpers (without hackisly using them out of context). For instaces, generating actions for forms can’t be done automatically (yet). So, why not add a little method to your form?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | /** * set the action based on a route * * @param array $params * @param string $routeName * @param bool $reset */ public function setRouteAction($params = array(), $routeName = null, $reset = false) { $frontController = Zend_Controller_Front::getInstance(); //the FC $router = $frontController->getRouter(); //the router (assumes rewrite router) if ($reset) { $routeName = 'default'; } //hmm... this may lead to unexpected results //but so will getting the current route name if ($routeName == null) { try { $routeName = $router->getCurrentRouteName(); } catch (Zend_Controller_Router_Exception $e) { $routeName = 'default'; } } //requested routename/default $route = $router->getRoute($routeName); //the current route $action = rtrim($frontController->getBaseUrl(), '/') . '/'; $action .= $route->assemble($params, $reset); $this->setAction($action); } |
Comments
So what if your route is named ‘null’? You’d better change == to === (or use is_null())
Also, is there a reason you don’t enforce the array type on the $params parameter?
Thanks Naneau fo great article. Now I know how to generate URL links for newly added articles in my future CMS:
$route->assemble();