16.09 | Quick Tip: Lithium Redirect

Learn how to correctly redirect URLs based on the Request information.

While migrating lithium_bin as part of research over to MongoDB (from CouchDB), I found the following snippet in the routes.php file:

  1. Router::connect('/', array(), function($request) {
  2. $location = array('controller' => 'pastes', 'action' => 'add');
  3. return new Response(compact('location'));
  4. });

This means that when the user enters the application via the root url (/), he instantly gets redirected to /pastes/add (or a different URL if you have custom routes configured).

This may seem ok at first, but there's a problem. It doesn't take URLs into account that don't live directly under the document root. So if your application lives under http://localhost/pastium/, it will redirect you to http://localhost/pastes/add/ which is not really what you want. Instead, do it like this:

  1. Router::connect('/', array(), function($request) {
  2. $location = Router::match('Pastes::add', $request);
  3. return new Response(compact('location'));
  4. });

In this snippet, the Router takes the current Request into account and returns the correct location (based on the reverse routing information). Now it should redirect you correctly to http://localhost/pastium/pastes/add/.

By the way, this is extracted from the Controller::redirect method, which is implemented in a similar way:

  1. public function redirect($url, array $options = array()) {
  2. //...
  3. $this->_filter(__METHOD__, $params, function($self, $params) use ($router) {
  4. $options = $params['options'];
  5. $location = $options['location'] ?: $router::match($params['url'], $self->request);
  6. $self->render(compact('location') + $options);
  7. });
  8. //...
  9. }

If you have any ideas on how to improve this further, feel free to comment below!