Skip to content
jdp edited this page Sep 13, 2010 · 5 revisions

Routing is where all of Tessera’s power comes from. Routes basically define what URL patterns are mapped to which methods in your application class. You can use two types of routes: named params and splats, or raw regular expressions.

The Easy Route

The simplest way to route is with named parameters and splats. Named parameters are denoted by a $ in front of their name, and are available in the $this->params variable by name or position. Splats act as wildcards, and aren’t named. They’re only available by position, but a convience variable $this->splats is also available. A regular splat is denoted by an asterisk, and will match anything up to a forward slash. A double-asterisk splat is greedy, and will even match forward slashes.

require 'tessera.php';

class ArguableApp extends Tessera {
    function foo() {
        echo "Bar is {$this->params['bar']}, and that's that";
    }
}

$basic = new ArguableApp(array(
    '/foo/$bar' => 'foo'
));

For the rest of this writeup, assume that the code is saved as arguable.php on your domain, tesseratic.com.

In the ArguableApp application, only one route is defined. The route /foo/$bar is mapped to the ArguableApp::foo method. The $bar part of the route is a variable, meaning that any call to /foo/* will be matched, and the matched text will be passed as a parameter to the ArguableApp::foo method. For example, tesseratic.com/arguable.php?/foo/xyzzy will match, and $this->params['bar'] inside of ArguableApp::foo will equal "xyzzy".

The Route Less Traveled

Internally, routes are compiled to regular expressions, and parameter variables are compiled to (\w+), so keep that in mind when naming them. Routes can also be considerably more complex. If you add a new route to the application like this:

$basic = new ArguableApp(array(
    '/foo/$bar' => 'foo',
    '/bar/$baz/zip/$zap' => 'bar'
));

And the associated method:

function bar($baz, $zip) {
    echo "Now we're getting nutty with {$baz} and {$zip}.";
}

Requests to tesseratic.com/arguable.php?/bar/squirtle/zip/charmander will match, and $baz will equal "squirtle" and $zip will equal "charmander". This example also demonstrates that you can provide the names of parameters as functions to methods as a small convenience.

NOTE: PHP doesn’t support named arguments, its function arguments are purely positional. If I have /bar/$baz/$zip mapped to a function defined as bar($zip, $baz), $zip is actually going to be the value from $baz and $baz will be the value from $zip.

Splat: Messy Routes

Splats are here to help route corner cases without having to resort to regular expressions. A simple example:

class App extends Tessera {
    function foo() {
        echo "Splat value: {$this->splat[0]}";
    }
}
$app = new App(array(
    '/foo/*' => 'foo';
));

You can also use a double asterisk to match splats that can contain a forward slash.

Irregular Routes with Regular Expressions

Maybe you have a corner case that you can’t accomplish with params and splats, and you need the full power of regular expressions. If you begin a route with a circumflex (^), the router will leave it as-is when matching URLs against it.

class App extends Tessera {
    function foo() {
        echo "Capture value: {$this->params[0]}";
    }
}
$app = new App(array(
    '^/foo/(\w+)' => 'foo';
));

Captures are still available in $this->params, but only by position, and starting from zero.

Why are URLs so ugly?

While reading this, you probably noticed and wondered: “Why are all my routes in the query string? That’s terribly ugly.” That’s because I want the distribution to be server-agnostic. It would be trivial to add some rewrite rules to your server to hide away the .php extensions and query string marker. In fact, it’s all on the deployment page.