19 Nov 2010

Lithium Routes And MongoDB

Lithium comes with a powerful and flexible routing system. However, in its default configuration, you may encounter some problems with MongoDB-ObjectIDs and reverse routing. ObjectIDs are usually the “primary keys” of your Document in MongoDB, are 12 bytes long and consist of numbers and characters from ‘a’ to ‘f’. A typical ObjectID would look similar to 4ce2d9f99436485e05000000.

If you take a closer look at the default routes that ship with Lithium, you’ll maybe notice that the :id part only matches numbers (and not characters).

Router::connect('/{:controller}/{:action}/{:id:[0-9]+}.{:type}', array('id' => null));
Router::connect('/{:controller}/{:action}/{:id:[0-9]+}');
Router::connect('/{:controller}/{:action}/{:args}');

With this setup a call to $this->html->link() with an MongoDB-ObjectID set as id won’t work because the router is not able to find a matching route (this is called reverse routing). The solution to this “problem” is, that we need to modify the :id-part of the Router::connect-calls. Replace your default routes with the following code:

Router::connect('/{:controller}/{:action}/{:id:[0-9a-f]{24}}.{:type}', array('id' => null));
Router::connect('/{:controller}/{:action}/{:id:[0-9a-f]{24}}');
Router::connect('/{:controller}/{:action}/{:args}');

Now everything should work as expected with li3 and MongoDB ObjectIDs. A final note for the interested reader: if you leave out the {24}-quantifier, then a route like /posts/add won’t work because add would also be a valid id to the router.

comments powered by Disqus