Routing
Configuration of routing and dispatching is done via the project-level config/
class files. If a route needs to be available in every config mode,
edit the project-level config/Common.php class file. If it only needs
to be available in a specific mode, e.g. dev, then edit the config file
for that mode (config/Dev.php).
The modify() method is where we get the router service (‘aura/web-kernel:router’)
and add routes to the application.
1 <?php
2 namespace Aura\Framework_Project\_Config;
3
4 use Aura\Di\Config;
5 use Aura\Di\Container;
6
7 class Common extends Config
8 {
9 public function define(Container $di)
10 {
11 // define params, setters, and services here
12 }
13
14 public function modify(Container $di)
15 {
16 // get the router service
17 $router = $di->get('aura/web-kernel:router');
18 // ... your application routes go below
19 }
20 }
The aura/web-kernel:router is an object of type Aura\Router\Router . So if you are
familiar with Aura.Router then
you are done with this chapter, else read on.
Aura framework can act both as a micro framework or full stack framework. If you are using it as a micro framework, you can set a Closure as the action value, else set the same name of the action in the dispatcher. Don’t worry, we will cover dispatching in next chapter.
Note: This chapter gives you a basic understanding of the different types of methods available in router.
Adding a Route
We will not be showing the whole config file to reduce the space used.
This document assumes you are adding the route in the modify() method after
getting the router service.
To create a route, call the add() method on the Router. Named path-info
params are placed inside braces in the path.
1 // add a simple named route without params
2 $router->add('home', '/');
3
4 // add a simple unnamed route with params
5 $router->add(null, '/{action}/{id}');
6
7 // add a named route with an extended specification
8 $router->add('blog.read', '/blog/read/{id}{format}')
9 ->addTokens(array(
10 'id' => '\d+',
11 'format' => '(\.[^/]+)?',
12 ))
13 ->addValues(array(
14 'action' => 'BlogReadAction',
15 'format' => '.html',
16 ));
You can create a route that matches only against a particular HTTP method
as well. The following Router methods are identical to add() but require
the related HTTP method:
$router->addGet()$router->addDelete()$router->addOption()$router->addPatch()$router->addPost()$router->addPut()
Advanced Usage
Extended Route Specification
You can extend a route specification with the following methods:
-
addTokens()– Adds regular expression subpatterns that params must match.1addTokens(array(2'id'=>'\d+',3))Note that
setTokens()is also available, but this will replace any previous subpatterns entirely, instead of merging with the existing subpatterns. -
addServer()– Adds regular expressions that server values must match.1addServer(array(2'REQUEST_METHOD'=>'PUT|PATCH',3))Note that
setServer()is also available, but this will replace any previous expressions entirely, instead of merging with the existing expressions. -
addValues()– Adds default values for the params.1addValues(array(2'year'=>'1979',3'month'=>'11',4'day'=>'07'5))Note that
setValues()is also available, but this will replace any previous default values entirely, instead of merging with the existing default value. -
setSecure()– Whentruethe$server['HTTPS']value must be on, or the request must be on port 443; whenfalse, neither of those must be in place. -
setWildcard()– Sets the name of a wildcard param; this is where arbitrary slash-separated values appearing after the route path will be stored. -
setRoutable()– Whenfalsethe route will be used only for generating paths, not for matching (trueby default). -
setIsMatchCallable()– A custom callable with the signaturefunction(array $server, \ArrayObject $matches)that returns true on a match, or false if not. This allows developers to build any kind of matching logic for the route, and to change the$matchesfor param values from the path. -
setGenerateCallable()– A custom callable with the signaturefunction(\ArrayObject $data). This allows developers to modify the data for path interpolation.
Here is a full extended route specification named read:
1 $router->add('blog.read', '/blog/read/{id}{format}')
2 ->addTokens(array(
3 'id' => '\d+',
4 'format' => '(\.[^/]+)?',
5 'REQUEST_METHOD' => 'GET|POST',
6 ))
7 ->addValues(array(
8 'id' => 1,
9 'format' => '.html',
10 ))
11 ->setSecure(false)
12 ->setRoutable(false)
13 ->setIsMatchCallable(function(array $server, \ArrayObject $matches) {
14
15 // disallow matching if referred from example.com
16 if ($server['HTTP_REFERER'] == 'http://example.com') {
17 return false;
18 }
19
20 // add the referer from $server to the match values
21 $matches['referer'] = $server['HTTP_REFERER'];
22 return true;
23
24 })
25 ->setGenerateCallable(function (\ArrayObject $data) {
26 $data['foo'] = 'bar';
27 });
Default Route Specifications
You can set the default route specifications with the following Router methods; the values will apply to all routes added thereafter.
1 // add to the default 'tokens' expressions; setTokens() is also available
2 $router->addTokens(array(
3 'id' => '\d+',
4 ));
5
6 // add to the default 'server' expressions; setServer() is also available
7 $router->addServer(array(
8 'REQUEST_METHOD' => 'PUT|PATCH',
9 ));
10
11 // add to the default param values; setValues() is also available
12 $router->addValues(array(
13 'format' => null,
14 ));
15
16 // set the default 'secure' value
17 $router->setSecure(true);
18
19 // set the default wildcard param name
20 $router->setWildcard('other');
21
22 // set the default 'routable' flag
23 $router->setRoutable(false);
24
25 // set the default 'isMatch()' callable
26 $router->setIsMatchCallable(function (...) { ... });
27
28 // set the default 'generate()' callable
29 $router->setGenerateCallable(function (...) { ... });
Simple Routes
You don’t need to specify an extended route specification. With the following simple route …
1 $router->add('archive', '/archive/{year}/{month}/{day}');
… the Router will use a default subpattern that matches everything except slashes for the path params. Thus, the above simple route is equivalent to the following extended route:
1 $router->add('archive', '/archive/{year}/{month}/{day}')
2 ->addTokens(array(
3 'year' => '[^/]+',
4 'month' => '[^/]+',
5 'day' => '[^/]+',
6 ));
Automatic Params
The Router will automatically populate values for the action
route param if one is not set manually.
1 // ['action' => 'foo.bar'] because it has not been set otherwise
2 $router->add('foo.bar', '/path/to/bar');
3
4 // ['action' => 'zim'] because we add it explicitly
5 $router->add('foo.dib', '/path/to/dib')
6 ->addValues(array('action' => 'zim'));
7
8 // the 'action' param here will be whatever the path value for {action} is
9 $router->add('/path/to/{action}');
Optional Params
Sometimes it is useful to have a route with optional named params. None, some, or all of the optional params may be present, and the route will still match.
To specify optional params, use the notation {/param1,param2,param3} in the
path. For example:
1 $router->add('archive', '/archive{/year,month,day}')
2 ->addTokens(array(
3 'year' => '\d{4}',
4 'month' => '\d{2}',
5 'day' => '\d{2}'
6 ));
|
The leading slash separator is inside the params token, not outside. |
With that, the following routes will all match the ‘archive’ route, and will set the appropriate values:
1 /archive
2 /archive/1979
3 /archive/1979/11
4 /archive/1979/11/07
Optional params are sequentially optional. This means that, in the above example, you cannot have a “day” without a “month”, and you cannot have a “month” without a “year”.
Only one set of optional params per path is recognized by the Router.
Optional params belong at the end of a route path; placing them elsewhere may result in unexpected behavior.
Wildcard Params
Sometimes it is useful to allow the trailing part of the path be anything at
all. To allow arbitrary trailing params on a route, extend the route
definition with setWildcard() to specify param name under which the
arbitrary trailing param values will be stored.
1 $router->add('wild_post', '/post/{id}')
2 ->setWildcard('other');
Attaching Route Groups
You can add a series of routes all at once under a single “mount point” in
your application. For example, if you want all your blog-related routes to be
mounted at /blog in your application, you can do this:
1 $name_prefix = 'blog';
2 $path_prefix = '/blog';
3
4 $router->attach($name_prefix, $path_prefix, function ($router) {
5
6 $router->add('browse', '{format}')
7 ->addTokens(array(
8 'format' => '(\.json|\.atom|\.html)?'
9 ))
10 ->addValues(array(
11 'format' => '.html',
12 ));
13
14 $router->add('read', '/{id}{format}', array(
15 ->addTokens(array(
16 'id' => '\d+',
17 'format' => '(\.json|\.atom|\.html)?'
18 )),
19 ->addValues(array(
20 'format' => '.html',
21 ));
22
23 $router->add('edit', '/{id}/edit{format}', array(
24 ->addTokens(array(
25 'id' => '\d+',
26 'format' => '(\.json|\.atom|\.html)?'
27 ))
28 ->addValues(array(
29 'format' => '.html',
30 ));
31 });
Each of the route names will be prefixed with ‘blog.’, and each of the route paths
will be prefixed with /blog, so the effective route names and paths become:
blog.browse => /blog{format}blog.read => /blog/{id}{format}blog.edit => /blog/{id}/edit{format}
You can set other route specification values as part of the attachment specification; these will be used as the defaults for each attached route, so you don’t need to repeat common information. (Setting these values will not affect routes outside the attached group.)
1 $name_prefix = 'blog';
2 $path_prefix = '/blog';
3
4 $router->attach($name_prefix, $path_prefix, function ($router) {
5
6 $router->setTokens(array(
7 'id' => '\d+',
8 'format' => '(\.json|\.atom)?'
9 ));
10
11 $router->setValues(array(
12 'format' => '.html',
13 ));
14
15 $router->add('browse', '');
16 $router->add('read', '/{id}{format}');
17 $router->add('edit', '/{id}/edit');
18 });
Attaching REST Resource Routes
The router can attach a series of REST resource routes for you with the
attachResource() method:
1 $router->attachResource('blog', '/blog');
That method call will result in the following routes being added:
| Route Name | HTTP Method | Route Path | Purpose |
|---|---|---|---|
| blog.browse | GET | /blog{format} | Browse multiple resources |
| blog.read | GET | /blog/{id}{format} | Read a single resource |
| blog.edit | GET | /blog/{id}/edit | The form for editing a resource |
| blog.add | GET | /blog/add | The form for adding a resource |
| blog.delete | DELETE | /blog/{id} | Delete a single resource |
| blog.create | POST | /blog | Create a new resource |
| blog.update | PATCH | /blog/{id} | Update part of an existing resource |
| blog.replace | PUT | /blog/{id} | Replace an entire existing resource |
The {id} token is whatever has already been defined in the router; if not
already defined, it will be any series of numeric digits. Likewise, the
{format} token is whatever has already been defined in the router; if not
already defined, it is an optional dot-format file extension (including the
dot itself).
The action value is the same as the route name.
If you want calls to attachResource() to create a different series of REST
routes, use the setResourceCallable() method to set your own callable to
create them.
1 $router->setResourceCallable(function ($router) {
2 $router->setTokens(array(
3 'id' => '([a-f0-9]+)'
4 ));
5 $router->addPost('create', '/{id}');
6 $router->addGet('read', '/{id}');
7 $router->addPatch('update', '/{id}');
8 $router->addDelete('delete', '/{id}');
9 });
The example will cause only four CRUD routes, using hexadecimal resource IDs,
to be added for the resource when you call attachResource().