PageRenderTime 50ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/docs/en/02_Developer_Guides/02_Controllers/02_Routing.md

http://github.com/silverstripe/sapphire
Markdown | 297 lines | 225 code | 72 blank | 0 comment | 0 complexity | 367680d46028692a3c9508433ab8dce5 MD5 | raw file
Possible License(s): BSD-3-Clause, MIT, CC-BY-3.0, GPL-2.0, AGPL-1.0, LGPL-2.1
  1. ---
  2. title: Routing
  3. summary: A more in depth look at how to map requests to particular controllers and actions.
  4. ---
  5. # Routing
  6. 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
  7. for our `TeamController` mapping any `teams` URL to our `TeamController`
  8. [info]
  9. If you're using the `cms` module with and dealing with `Page` objects then for your custom `Page Type` controllers you
  10. would extend `ContentController` or `PageController`. You don't need to define the routes value as the `cms` handles
  11. routing.
  12. [/info]
  13. These routes by standard, go into a `routes.yml` file in your applications `_config` folder alongside your other
  14. [Configuration](../configuration) information.
  15. **app/_config/routes.yml**
  16. ```yml
  17. ---
  18. Name: approutes
  19. After:
  20. - '#rootroutes'
  21. - '#coreroutes'
  22. ---
  23. SilverStripe\Control\Director:
  24. rules:
  25. 'teams//$Action/$ID/$Name': 'TeamController'
  26. 'player/': 'PlayerController'
  27. '': 'HomeController'
  28. ```
  29. [notice]
  30. To understand the syntax for the `routes.yml` file better, read the [Configuration](../configuration) documentation.
  31. [/notice]
  32. ## Parameters
  33. ```yml
  34. 'teams//$Action/$ID/$Name': 'TeamController'
  35. ```
  36. This route has defined that any URL beginning with `team` should create, and be handled by a `TeamController` instance.
  37. It also contains 3 `parameters` or `params` for short. `$Action`, `$ID` and `$Name`. These variables are placeholders
  38. which will be filled when the user makes their request. Request parameters are available on the `HTTPRequest` object
  39. and able to be pulled out from a controller using `$this->getRequest()->param($name)`.
  40. [info]
  41. All Controllers have access to `$this->getRequest()` for the request object and `$this->getResponse()` for the response.
  42. [/info]
  43. Here is what those parameters would look like for certain requests
  44. ```php
  45. // GET /teams/
  46. print_r($this->getRequest()->params());
  47. // Array
  48. // (
  49. // [Action] => null
  50. // [ID] => null
  51. // [Name] => null
  52. // )
  53. // GET /teams/players/
  54. print_r($this->getRequest()->params());
  55. // Array
  56. // (
  57. // [Action] => 'players'
  58. // [ID] => null
  59. // [Name] => null
  60. // )
  61. // GET /teams/players/1
  62. print_r($this->getRequest()->params());
  63. // Array
  64. // (
  65. // [Action] => 'players'
  66. // [ID] => 1
  67. // [Name] => null
  68. // )
  69. ```
  70. You can also fetch one parameter at a time.
  71. ```php
  72. // GET /teams/players/1/
  73. echo $this->getRequest()->param('ID');
  74. // returns '1'
  75. ```
  76. ## URL Patterns
  77. The [RequestHandler](api:SilverStripe\Control\RequestHandler) class will parse all rules you specify against the following patterns. The most specific rule
  78. will be the one followed for the response.
  79. [alert]
  80. A rule must always start with alphabetical ([A-Za-z]) characters or a $Variable declaration
  81. [/alert]
  82. | Pattern | Description |
  83. | ----------- | --------------- |
  84. | `$` | **Param Variable** - Starts the name of a paramater variable, it is optional to match this unless ! is used |
  85. | `!` | **Require Variable** - Placing this after a parameter variable requires data to be present for the rule to match |
  86. | `//` | **Shift Point** - Declares that only variables denoted with a $ are parsed into the $params AFTER this point in the regex |
  87. ```yml
  88. 'teams/$Action/$ID/$OtherID': 'TeamController'
  89. # /teams/
  90. # /teams/players/
  91. # /teams/
  92. ```
  93. Standard URL handler syntax. For any URL that contains 'team' this rule will match and hand over execution to the
  94. matching controller. The `TeamsController` is passed an optional action, id and other id parameters to do any more
  95. decision making.
  96. ```yml
  97. 'teams/$Action!/$ID!/': 'TeamController'
  98. ```
  99. This does the same matching as the previous example, any URL starting with `teams` will look at this rule **but** both
  100. `$Action` and `$ID` are required. Any requests to `team/` will result in a `404` error rather than being handed off to
  101. the `TeamController`.
  102. ```yml
  103. 'admin/help//$Action/$ID: 'AdminHelp'
  104. ```
  105. Match an url starting with `/admin/help/`, but don't include `/help/` as part of the action (the shift point is set to
  106. start parsing variables and the appropriate controller action AFTER the `//`).
  107. ### Wildcard URL Patterns
  108. As of SilverStripe 4.6 there are two wildcard patterns that can be used. `$@` and `$*`. These parameters can only be used
  109. at the end of a URL pattern, any further rules are ignored.
  110. Inspired by bash variadic variable syntax there are two ways to capture all URL parameters without having to explicitly
  111. specify them in the URL rule.
  112. Using `$@` will split the URL into numbered parameters (`$1`, `$2`, ..., `$n`). For example:
  113. ```php
  114. <?php
  115. class StaffController extends \SilverStripe\Control\Controller
  116. {
  117. private static $url_handlers = [
  118. 'staff/$@' => 'index',
  119. ];
  120. public function index($request)
  121. {
  122. // GET /staff/managers/bob
  123. $request->latestParam('$1'); // managers
  124. $request->latestParam('$2'); // bob
  125. }
  126. }
  127. ```
  128. Alternatively, if access to the parameters is not required in this way then it is possible to use `$*` to match all
  129. URL parameters but not collect them in the same way:
  130. ```php
  131. <?php
  132. class StaffController extends \SilverStripe\Control\Controller
  133. {
  134. private static $url_handlers = [
  135. 'staff/$*' => 'index',
  136. ];
  137. public function index($request)
  138. {
  139. // GET /staff/managers/bob
  140. $request->remaining(); // managers/bob
  141. }
  142. }
  143. ```
  144. ## URL Handlers
  145. [alert]
  146. You **must** use the **$url_handlers** static array described here if your URL
  147. pattern does not use the Controller class's default pattern of
  148. `$Action//$ID/$OtherID`. If you fail to do so, and your pattern has more than
  149. 2 parameters, your controller will throw the error "I can't handle sub-URLs of
  150. a *class name* object" with HTTP status 404.
  151. [/alert]
  152. In the above example the URLs were configured using the [Director](api:SilverStripe\Control\Director) rules in the **routes.yml** file. Alternatively
  153. you can specify these in your Controller class via the **$url_handlers** static array. This array is processed by the
  154. [RequestHandler](api:SilverStripe\Control\RequestHandler) at runtime once the `Controller` has been matched.
  155. This is useful when you want to provide custom actions for the mapping of `teams/*`. Say for instance we want to respond
  156. `coaches`, and `staff` to the one controller action `payroll`.
  157. **app/code/controllers/TeamController.php**
  158. ```php
  159. use SilverStripe\Control\Controller;
  160. class TeamController extends Controller
  161. {
  162. private static $allowed_actions = [
  163. 'payroll'
  164. ];
  165. private static $url_handlers = [
  166. 'staff/$ID/$Name' => 'payroll',
  167. 'coach/$ID/$Name' => 'payroll'
  168. ];
  169. ```
  170. The syntax for the `$url_handlers` array users the same pattern matches as the `YAML` configuration rules.
  171. Now lets consider a more complex example from a real project, where using
  172. **$url_handlers** is mandatory. In this example, the URLs are of the form
  173. `http://example.org/feed/go/`, followed by 5 parameters. The PHP controller
  174. class specifies the URL pattern in `$url_handlers`. Notice that it defines 5
  175. parameters.
  176. ```php
  177. use SilverStripe\CMS\Controllers\ContentController;
  178. class FeedController extends ContentController
  179. {
  180. private static $allowed_actions = ['go'];
  181. private static $url_handlers = [
  182. 'go/$UserName/$AuthToken/$Timestamp/$OutputType/$DeleteMode' => 'go'
  183. ];
  184. public function go()
  185. {
  186. $this->validateUser(
  187. $this->getRequest()->param('UserName'),
  188. $this->getRequest()->param('AuthToken')
  189. );
  190. /* more processing goes here */
  191. }
  192. }
  193. ```
  194. The YAML rule, in contrast, is simple. It needs to provide only enough information for the framework to choose the desired controller.
  195. ```yml
  196. Director:
  197. rules:
  198. 'feed': 'FeedController'
  199. ```
  200. ## Root URL Handlers
  201. In some cases, the Director rule covers the entire URL you intend to match, and you simply want the controller to respond to a 'root' request. This request will automatically direct to an `index()` method if it exists on the controller, but you can also set a custom method to use in `$url_handlers` with the `'/'` key:
  202. ```php
  203. use SilverStripe\Control\Controller;
  204. class BreadAPIController extends Controller
  205. {
  206. private static $allowed_actions = [
  207. 'getBreads',
  208. 'createBread',
  209. ];
  210. private static $url_handlers = [
  211. 'GET /' => 'getBreads',
  212. 'POST /' => 'createBread',
  213. ];
  214. ```
  215. <div class="alert" markdown="1">
  216. In SilverStripe Framework versions prior to 4.6, an empty key (`''`) must be used in place of the `'/'` key. When specifying an HTTP method, the empty string must be separated from the method (e.g. `'GET '`). The empty key and slash key are also equivalent in Director rules.
  217. </div>
  218. ## Related Lessons
  219. * [Creating filtered views](https://www.silverstripe.org/learn/lessons/v4/creating-filtered-views-1)
  220. * [Controller actions / DataObjects as pages](https://www.silverstripe.org/learn/lessons/v4/controller-actions-dataobjects-as-pages-1)
  221. ## Links
  222. * [Controller](api:SilverStripe\Control\Controller) API documentation
  223. * [Director](api:SilverStripe\Control\Director) API documentation
  224. * [Example routes: framework](https://github.com/silverstripe/silverstripe-framework/blob/master/_config/routes.yml)
  225. * [Example routes: cms](https://github.com/silverstripe/silverstripe-cms/blob/master/_config/routes.yml)