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 $di->get('aura/web-kernel:router')
and add routes to the application.
<?php
namespace Aura\Framework_Project\_Config;
use Aura\Di\Config;
use Aura\Di\Container;
class Common extends Config
{
public function define(Container $di)
{
// define params, setters, and services here
}
public function modify(Container $di)
{
// get the router service
$router = $di->get('aura/web-kernel:router');
// ... your application routes go below
}
}
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.
To create a route, call the add()
method on the Router. Named path-info params are placed inside braces in the path.
// add a simple named route without params
$router->add('home', '/');
// add a simple unnamed route with params
$router->add(null, '/{action}/{id}');
// add a named route with an extended specification
$router->add('blog.read', '/blog/read/{id}{format}')
->addTokens(array(
'id' => '\d+',
'format' => '(\.[^/]+)?',
))
->addValues(array(
'action' => 'BlogReadAction',
'format' => '.html',
));
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()
You can extend a route specification with the following methods:
addTokens()
– Adds regular expression subpatterns that params must
match.
addTokens(array(
'id' => '\d+',
))
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.
addServer(array(
'REQUEST_METHOD' => 'PUT|PATCH',
))
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.
addValues(array(
'year' => '1979',
'month' => '11',
'day' => '07'
))
Note that setValues()
is also available, but this will replace any
previous default values entirely, instead of merging with the existing
default value.
setSecure()
– When true
the $server['HTTPS']
value must be on, or the
request must be on port 443; when false
, 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()
– When false
the route will be used only for generating
paths, not for matching (true
by default).
setIsMatchCallable()
– A custom callable with the signature
function(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 $matches
for param values from the
path.
setGenerateCallable()
– A custom callable with the signature
function(\ArrayObject $data)
. This allows developers to modify the data
for path interpolation.
Here is a full extended route specification named read
:
$router->add('blog.read', '/blog/read/{id}{format}')
->addTokens(array(
'id' => '\d+',
'format' => '(\.[^/]+)?',
'REQUEST_METHOD' => 'GET|POST',
))
->addValues(array(
'id' => 1,
'format' => '.html',
))
->setSecure(false)
->setRoutable(false)
->setIsMatchCallable(function(array $server, \ArrayObject $matches) {
// disallow matching if referred from example.com
if ($server['HTTP_REFERER'] == 'http://example.com') {
return false;
}
// add the referer from $server to the match values
$matches['referer'] = $server['HTTP_REFERER'];
return true;
})
->setGenerateCallable(function (\ArrayObject $data) {
$data['foo'] = 'bar';
});
You can set the default route specifications with the following Router methods; the values will apply to all routes added thereafter.
// add to the default 'tokens' expressions; setTokens() is also available
$router->addTokens(array(
'id' => '\d+',
));
// add to the default 'server' expressions; setServer() is also available
$router->addServer(array(
'REQUEST_METHOD' => 'PUT|PATCH',
));
// add to the default param values; setValues() is also available
$router->addValues(array(
'format' => null,
));
// set the default 'secure' value
$router->setSecure(true);
// set the default wildcard param name
$router->setWildcard('other');
// set the default 'routable' flag
$router->setRoutable(false);
// set the default 'isMatch()' callable
$router->setIsMatchCallable(function (...) { ... });
// set the default 'generate()' callable
$router->setGenerateCallable(function (...) { ... });
You don’t need to specify an extended route specification. With the following simple route …
$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:
$router->add('archive', '/archive/{year}/{month}/{day}')
->addTokens(array(
'year' => '[^/]+',
'month' => '[^/]+',
'day' => '[^/]+',
));
The Router will automatically populate values for the action
route param if one is not set manually.
// ['action' => 'foo.bar'] because it has not been set otherwise
$router->add('foo.bar', '/path/to/bar');
// ['action' => 'zim'] because we add it explicitly
$router->add('foo.dib', '/path/to/dib')
->addValues(array('action' => 'zim'));
// the 'action' param here will be whatever the path value for {action} is
$router->add('/path/to/{action}');
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:
$router->add('archive', '/archive{/year,month,day}')
->addTokens(array(
'year' => '\d{4}',
'month' => '\d{2}',
'day' => '\d{2}'
));
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:
/archive
/archive/1979
/archive/1979/11
/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.
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.
$router->add('wild_post', '/post/{id}')
->setWildcard('other');
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:
$name_prefix = 'blog';
$path_prefix = '/blog';
$router->attach($name_prefix, $path_prefix, function ($router) {
$router->add('browse', '{format}')
->addTokens(array(
'format' => '(\.json|\.atom|\.html)?'
))
->addValues(array(
'format' => '.html',
));
$router->add('read', '/{id}{format}', array(
->addTokens(array(
'id' => '\d+',
'format' => '(\.json|\.atom|\.html)?'
)),
->addValues(array(
'format' => '.html',
));
$router->add('edit', '/{id}/edit{format}', array(
->addTokens(array(
'id' => '\d+',
'format' => '(\.json|\.atom|\.html)?'
))
->addValues(array(
'format' => '.html',
));
});
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.)
$name_prefix = 'blog';
$path_prefix = '/blog';
$router->attach($name_prefix, $path_prefix, function ($router) {
$router->setTokens(array(
'id' => '\d+',
'format' => '(\.json|\.atom)?'
));
$router->setValues(array(
'format' => '.html',
));
$router->add('browse', '');
$router->add('read', '/{id}{format}');
$router->add('edit', '/{id}/edit');
});
The router can attach a series of REST resource routes for you with the attachResource()
method:
$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}{format} | 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.
$router->setResourceCallable(function ($router) {
$router->setTokens(array(
'id' => '([a-f0-9]+)'
));
$router->addPost('create', '/{id}');
$router->addGet('read', '/{id}');
$router->addPatch('update', '/{id}');
$router->addDelete('delete', '/{id}');
});
The example will cause only four CRUD routes, using hexadecimal resource IDs, to be added for the resource when you call attachResource()
.