# Controller Base controller class. You will extend this to take granular control over the actions and url handling of aspects of your SilverStripe site. ## Usage The following example is for a simple `[api:Controller]` class. If you're using the cms module and looking at Page_Controller instances you won't need to setup your own routes since the cms module handles these routes. `mysite/code/Controllers/FastFood.php` :::php order [ID] => 24 [Name] => cheesefries )
SilverStripe automatically adds a URL routing entry based on the controller's class name, so a `MyController` class is accessible through `http://yourdomain.com/MyController`.
## Access Control ### Through $allowed_actions All public methods on a controller are accessible by their name through the `$Action` part of the URL routing, so a `MyController->mymethod()` is accessible at `http://yourdomain.com/MyController/mymethod`. This is not always desireable, since methods can return internal information, or change state in a way that's not intended to be used through a URL endpoint. SilverStripe strongly recommends securing your controllers through defining a `$allowed_actions` array on the class, which allows whitelisting of methods, as well as a concise way to perform checks against permission codes or custom logic. :::php class MyController extends Controller { public static $allowed_actions = array( // someaction can be accessed by anyone, any time 'someaction', // So can otheraction 'otheraction' => true, // restrictedaction can only be people with ADMIN privilege 'restrictedaction' => 'ADMIN', // complexaction can only be accessed if $this->canComplexAction() returns true 'complexaction' '->canComplexAction' ); } There's a couple of rules guiding these checks: * Each controller is only responsible for access control on the methods it defines * If a method on a parent class is overwritten, access control for it has to be redefined as well * An action named "index" is whitelisted by default * A wildcard (`*`) can be used to define access control for all methods (incl. methods on parent classes) * Specific method entries in `$allowed_actions` overrule any `*` settings * Methods returning forms also count as actions which need to be defined * Form action methods (targets of `FormAction`) should NOT be included in `$allowed_actions`, they're handled separately through the form routing (see the ["forms" topic](/topics/forms)) * `$allowed_actions` can be defined on `Extension` classes applying to the controller. If the permission check fails, SilverStripe will return a "403 Forbidden" HTTP status. ### Through the action Each method responding to a URL can also implement custom permission checks, e.g. to handle responses conditionally on the passed request data. :::php class MyController extends Controller { public static $allowed_actions = array('myaction'); public function myaction($request) { if(!$request->getVar('apikey')) { return $this->httpError(403, 'No API key provided'); } return 'valid'; } } Unless you transform the response later in the request processing, it'll look pretty ugly to the user. Alternatively, you can use `ErrorPage::response_for()` to return a more specialized layout. Note: This is recommended as an addition for `$allowed_actions`, in order to handle more complex checks, rather than a replacement. ### Through the init() method After checking for allowed_actions, each controller invokes its `init()` method, which is typically used to set up common state in the controller, and include JavaScript and CSS files in the output which are used for any action. If an `init()` method returns a `SS_HTTPResponse` with either a 3xx or 4xx HTTP status code, it'll abort execution. This behaviour can be used to implement permission checks. :::php class MyController extends Controller { public static $allowed_actions = array(); public function init() { parent::init(); if(!Permission::check('ADMIN')) return $this->httpError(403); } } ## URL Handling In the above example the URLs were configured using the `[api:Director]` rules in the **routes.yml** file. Alternatively you can specify these in your Controller class via the **$url_handlers** static array (which gets processed by the `[api:RequestHandler]`). This is useful when you want to subvert the fixed action mapping of `fastfood/order/*` to the function **order**. In the case below we also want any orders coming through `/fastfood/drivethrough/` to use the same order function. `mysite/code/Controllers/FastFood.php` :::php class FastFood_Controller extends Controller { static $allowed_actions = array('drivethrough'); public static $url_handlers = array( 'drivethrough/$Action/$ID/$Name' => 'order' ); ## URL Patterns The `[api:RequestHandler]` class will parse all rules you specify against the following patterns. **A rule must always start with alphabetical ([A-Za-z]) characters or a $Variable declaration** | 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 | ## Examples See maetl's article in the Links below of a detailed explanation. `$Action/$ID/$OtherID` - Standard URL handler for a Controller. Take whatever `URLSegment` it is set to, find the Action to match a function in the controller, and parse two optional `$param` variables that will be named `ID` and `OtherID`. `admin/help//$Action/$ID` - 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 `//`) `tag/$Tag!` - Match an URL starting with `/tag/` after the controller's `URLSegment` and require it to have something after it. If the URLSegment is **order** then `/order/tag/34` and `/order/tag/asdf` match but `/order/tag/` will not You can use the `debug_request=1` switch from the [urlvariabletools](/reference/urlvariabletools) to see these in action. ## Redirection Controllers facilitate HTTP redirection. Note: These methods have been formerly located on the `[api:Director]` class. * `redirect("action-name")`: If there's no slash in the URL passed to redirect, then it is assumed that you want to go to a different action on the current controller. * `redirect("relative/url")`: If there is a slash in the URL, it's taken to be a normal URL. Relative URLs will are assumed to be relative to the site-root. * `redirect("http://www.absoluteurl.com")`: Of course, you can pass `redirect()` absolute URLs too. * `redirectBack()`: This will return you to the previous page. The `redirect()` method takes an optional HTTP status code, either `301` for permanent redirects, or `302` for temporary redirects (default). ## API Documentation `[api:Controller]` ## Links * `[api:Director]` class * [execution-pipeline](/reference/execution-pipeline) * [URL Handling in Controllers](http://maetl.net/silverstripe-url-handling) by maetl