2014-10-18 00:28:51 +02:00
title: Routing
summary: A more in depth look at how to map requests to particular controllers and actions.
# Routing
2017-07-03 03:22:12 +02:00
Routing is the process of mapping URL's to [Controller ](api:SilverStripe\Control\Controller ) and actions. In the introduction we defined a new custom route
2016-12-30 00:17:15 +01:00
for our `TeamController` mapping any `teams` URL to our `TeamController`
2014-10-18 00:28:51 +02:00
< div class = "info" markdown = "1" >
If you're using the `cms` module with and dealing with `Page` objects then for your custom `Page Type` controllers you
2016-12-30 00:17:15 +01:00
would extend `ContentController` or `PageController` . You don't need to define the routes value as the `cms` handles
2014-10-18 00:28:51 +02:00
routing.
< / div >
These routes by standard, go into a `routes.yml` file in your applications `_config` folder alongside your other
[Configuration ](../configuration ) information.
**mysite/_config/routes.yml**
2016-12-30 00:17:15 +01:00
```yml
---
Name: mysiteroutes
2018-02-27 17:42:20 +01:00
After:
- '#rootroutes'
- '#coreroutes'
2016-12-30 00:17:15 +01:00
---
2017-02-03 18:06:02 +01:00
SilverStripe\Control\Director:
2016-12-30 00:17:15 +01:00
rules:
'teams//$Action/$ID/$Name': 'TeamController'
'player/': 'PlayerController'
'': 'HomeController'
```
2014-10-18 00:28:51 +02:00
< div class = "notice" markdown = "1" >
To understand the syntax for the `routes.yml` file better, read the [Configuration ](../configuration ) documentation.
< / div >
## Parameters
2016-12-30 00:17:15 +01:00
```yml
'teams//$Action/$ID/$Name': 'TeamController'
```
2014-10-18 00:28:51 +02:00
This route has defined that any URL beginning with `team` should create, and be handled by a `TeamController` instance.
It also contains 3 `parameters` or `params` for short. `$Action` , `$ID` and `$Name` . These variables are placeholders
2016-09-09 08:43:05 +02:00
which will be filled when the user makes their request. Request parameters are available on the `HTTPRequest` object
2015-04-30 01:04:08 +02:00
and able to be pulled out from a controller using `$this->getRequest()->param($name)` .
2014-10-18 00:28:51 +02:00
< div class = "info" markdown = "1" >
2015-08-14 02:39:33 +02:00
All Controllers have access to `$this->getRequest()` for the request object and `$this->getResponse()` for the response.
2014-10-18 00:28:51 +02:00
< / div >
Here is what those parameters would look like for certain requests
2016-12-30 00:17:15 +01:00
```php
// GET /teams/
2014-10-18 00:28:51 +02:00
2016-12-30 00:17:15 +01:00
print_r($this->getRequest()->params());
2014-10-18 00:28:51 +02:00
2016-12-30 00:17:15 +01:00
// Array
// (
// [Action] => null
// [ID] => null
// [Name] => null
// )
2014-10-18 00:28:51 +02:00
2016-12-30 00:17:15 +01:00
// GET /teams/players/
2014-10-18 00:28:51 +02:00
2016-12-30 00:17:15 +01:00
print_r($this->getRequest()->params());
2014-10-18 00:28:51 +02:00
2016-12-30 00:17:15 +01:00
// Array
// (
// [Action] => 'players'
// [ID] => null
// [Name] => null
// )
2014-10-18 00:28:51 +02:00
2016-12-30 00:17:15 +01:00
// GET /teams/players/1
2014-10-18 00:28:51 +02:00
2016-12-30 00:17:15 +01:00
print_r($this->getRequest()->params());
2014-10-18 00:28:51 +02:00
2016-12-30 00:17:15 +01:00
// Array
// (
// [Action] => 'players'
// [ID] => 1
// [Name] => null
// )
2017-08-03 05:35:09 +02:00
2016-12-30 00:17:15 +01:00
```
2014-10-18 00:28:51 +02:00
You can also fetch one parameter at a time.
2016-12-30 00:17:15 +01:00
```php
// GET /teams/players/1/
2014-10-18 00:28:51 +02:00
2016-12-30 00:17:15 +01:00
echo $this->getRequest()->param('ID');
// returns '1'
```
2014-10-18 00:28:51 +02:00
## URL Patterns
2017-07-03 03:22:12 +02:00
The [RequestHandler ](api:SilverStripe\Control\RequestHandler ) class will parse all rules you specify against the following patterns. The most specific rule
2014-10-18 00:28:51 +02:00
will be the one followed for the response.
< div class = "alert" >
A rule must always start with alphabetical ([A-Za-z]) characters or a $Variable declaration
< / div >
| Pattern | Description |
| ----------- | --------------- |
| `$` | **Param Variable** - Starts the name of a paramater variable, it is optional to match this unless ! is used |
| `!` | **Require Variable** - Placing this after a parameter variable requires data to be present for the rule to match |
| `//` | **Shift Point** - Declares that only variables denoted with a $ are parsed into the $params AFTER this point in the regex |
2016-12-30 00:17:15 +01:00
```yml
'teams/$Action/$ID/$OtherID': 'TeamController'
2014-10-18 00:28:51 +02:00
2016-12-30 00:17:15 +01:00
# /teams/
# /teams/players/
# /teams/
```
2014-10-18 00:28:51 +02:00
Standard URL handler syntax. For any URL that contains 'team' this rule will match and hand over execution to the
matching controller. The `TeamsController` is passed an optional action, id and other id parameters to do any more
decision making.
2016-12-30 00:17:15 +01:00
```yml
'teams/$Action!/$ID!/': 'TeamController'
```
2014-10-18 00:28:51 +02:00
This does the same matching as the previous example, any URL starting with `teams` will look at this rule **but** both
`$Action` and `$ID` are required. Any requests to `team/` will result in a `404` error rather than being handed off to
the `TeamController` .
2016-12-30 00:17:15 +01:00
```yml
'admin/help//$Action/$ID: 'AdminHelp'
```
2014-10-18 00:28:51 +02:00
Match an url starting with `/admin/help/` , but don't include `/help/` as part of the action (the shift point is set to
start parsing variables and the appropriate controller action AFTER the `//` ).
## URL Handlers
2015-03-05 20:48:31 +01:00
< div class = "alert" markdown = "1" >
You **must** use the ** $url_handlers** static array described here if your URL
pattern does not use the Controller class's default pattern of
`$Action//$ID/$OtherID` . If you fail to do so, and your pattern has more than
2 parameters, your controller will throw the error "I can't handle sub-URLs of
a *class name* object" with HTTP status 404.
< / div >
2017-07-03 03:22:12 +02:00
In the above example the URLs were configured using the [Director ](api:SilverStripe\Control\Director ) rules in the **routes.yml** file. Alternatively
2014-10-18 00:28:51 +02:00
you can specify these in your Controller class via the ** $url_handlers** static array. This array is processed by the
2017-07-03 03:22:12 +02:00
[RequestHandler ](api:SilverStripe\Control\RequestHandler ) at runtime once the `Controller` has been matched.
2014-10-18 00:28:51 +02:00
This is useful when you want to provide custom actions for the mapping of `teams/*` . Say for instance we want to respond
`coaches` , and `staff` to the one controller action `payroll` .
**mysite/code/controllers/TeamController.php**
2017-07-03 03:22:12 +02:00
```php
2016-12-30 00:17:15 +01:00
use SilverStripe\Control\Controller;
2014-10-18 00:28:51 +02:00
2016-12-30 00:17:15 +01:00
class TeamController extends Controller
{
2017-08-03 05:35:09 +02:00
private static $allowed_actions = [
2016-12-30 00:17:15 +01:00
'payroll'
2017-08-03 05:35:09 +02:00
];
2014-10-18 00:28:51 +02:00
2017-08-03 05:35:09 +02:00
private static $url_handlers = [
2016-12-30 00:17:15 +01:00
'staff/$ID/$Name' => 'payroll',
'coach/$ID/$Name' => 'payroll'
2017-08-03 05:35:09 +02:00
];
2016-12-30 00:17:15 +01:00
```
2014-10-18 00:28:51 +02:00
The syntax for the `$url_handlers` array users the same pattern matches as the `YAML` configuration rules.
2015-03-05 20:48:31 +01:00
Now let’ s consider a more complex example from a real project, where using
**$url_handlers** is mandatory. In this example, the URLs are of the form
`http://example.org/feed/go/` , followed by 5 parameters. The PHP controller
class specifies the URL pattern in `$url_handlers` . Notice that it defines 5
parameters.
2016-12-30 00:17:15 +01:00
```php
use SilverStripe\CMS\Controllers\ContentController;
class FeedController extends ContentController
{
2017-08-03 05:35:09 +02:00
private static $allowed_actions = ['go'];
private static $url_handlers = [
2016-12-30 00:17:15 +01:00
'go/$UserName/$AuthToken/$Timestamp/$OutputType/$DeleteMode' => 'go'
2017-08-03 05:35:09 +02:00
];
2015-03-05 20:48:31 +01:00
2016-12-30 00:17:15 +01:00
public function go()
{
$this->validateUser(
$this->getRequest()->param('UserName'),
$this->getRequest()->param('AuthToken')
);
/* more processing goes here */
}
}
2018-03-29 10:07:57 +02:00
```
2015-03-05 20:48:31 +01:00
2018-03-29 10:07:57 +02:00
The YAML rule, in contrast, is simple. It needs to provide only enough information for the framework to choose the desired controller.
2017-08-03 05:35:09 +02:00
2016-12-30 00:17:15 +01:00
```yml
Director:
rules:
'feed': 'FeedController'
```
2015-03-05 20:48:31 +01:00
2017-11-27 04:39:17 +01:00
## Related Lessons
* [Creating filtered views ](https://www.silverstripe.org/learn/lessons/v4/creating-filtered-views-1 )
2017-11-28 02:11:52 +01:00
* [Controller actions / DataObjects as pages ](https://www.silverstripe.org/learn/lessons/v4/controller-actions-dataobjects-as-pages-1 )
2018-03-29 10:07:57 +02:00
2014-11-15 04:01:47 +01:00
## Links
2014-10-18 00:28:51 +02:00
2017-07-03 03:22:12 +02:00
* [Controller ](api:SilverStripe\Control\Controller ) API documentation
* [Director ](api:SilverStripe\Control\Director ) API documentation
2014-11-15 04:01:47 +01:00
* [Example routes: framework ](https://github.com/silverstripe/silverstripe-framework/blob/master/_config/routes.yml )
* [Example routes: cms ](https://github.com/silverstripe/silverstripe-cms/blob/master/_config/routes.yml )