Sunday, May 22, 2011

Customize the route compiler for Silex

Do you know Flask which is a microframework for Python. It looks like Silex and sinatora.
It allows you to use 'Variable Rules'. This is like below:

@app.route('/post/<int:post_id>')
def show_post(post_id):
    # show the post with the given id, the id is an integer
    pass

You can add the rule for each parameters, which are "int:", "float:" or "path:".
If you add "int:", this route accepts only integers and you add "path:", it is like the default but also accepts slashes.
you can implement by an assert method on Silex. Here is an example:

$app->get('/post/{post_id}', function ($post_id) {
    ...
})
->assert('post_id', '\d+')

You can see details in Requirements section of the document.

So I tried to implement it on the route of Silex. You can get the source code from my github branch.

If you use this version, you can write like this:

$app = new Silex\Application();
$app['route.compiler_class'] = 'Silex\\RouteAssertCompiler';

$app->get('/foo/{int:id}/{path:name}', function ($id, $name) {
    return sprintf("%d:%s", $id, $name);
});

I wrote a new RouteCompiler class, which is "RouteAssertCompiler" class and customized Application class which could load this new compiler class. So you have only to do is to set 'Silex\\RouteAssertCompiler' as 'route.compiler_class'.

If you access "/foo/3/a/b/c", this app returns "3:a/b/c" and if you access "/foo/a/b/c", then this route does not match.

I think this is simple and like it, but Silex has an assert method which is much flexible :)