* First cut * Temporarily disable composer.json for netlify build * POC * New recursive directory query, various refinements * Fix flexbox * new styled components plugin * Apply frontmatter delimiters * Mobile styles, animation * Search * Redesign, clean up * Nuke the cache, try again * fix file casing * Remove production env file * ID headers * Move app to new repo * Add frontmatter universally * Hide children changelogs * Add how to title * New callout tags * Revert inline code block change * Replace note callouts * Fix icons * Repalce images * Fix icon * Fix image links * Use proper SQL icon
6.8 KiB
title | summary |
---|---|
Introduction to a Controller | A brief look at the definition of a Controller, creating actions and how to respond to requests. |
Introduction to Controllers
The following example is for a simple Controller class. When building off the SilverStripe Framework you will
subclass the base Controller
class.
app/code/controllers/TeamController.php
use SilverStripe\Control\Controller;
use SilverStripe\Control\HTTPRequest;
class TeamController extends Controller
{
private static $allowed_actions = [
'players',
'index'
];
public function index(HTTPRequest $request)
{
// ..
}
public function players(HTTPRequest $request)
{
print_r($request->allParams());
}
}
Routing
We need to define the URL that this controller can be accessed on. In our case, the TeamsController
should be visible
at http://yoursite.com/teams/ and the players
custom action is at http://yoursite.com/team/players/.
[info]
If you're using the cms
module with and dealing with Page
objects then for your custom Page Type
controllers you
would extend ContentController
or PageController
. You don't need to define the routes value as the cms
handles
routing.
[/info]
[alert]
Make sure that after you have modified the routes.yml
file, that you clear your SilverStripe caches using ?flush=1
.
[/alert]
app/_config/routes.yml
---
Name: approutes
After: framework/_config/routes#coreroutes
---
SilverStripe\Control\Director:
rules:
'teams//$Action/$ID/$Name': 'TeamController'
For more information about creating custom routes, see the Routing documentation.
Actions
Controllers respond by default to an index
method. You don't need to define this method (as it's assumed) but you
can override the index()
response to provide custom data back to the Template and Views.
[notice]
It is standard in SilverStripe for your controller actions to be lowercasewithnospaces
[/notice]
Action methods can return one of four main things:
- an array. In this case the values in the array are available in the templates and the controller completes as usual by returning a HTTPResponse with the body set to the current template.
HTML
. SilverStripe will wrap theHTML
into aHTTPResponse
and set the status code to 200.- an HTTPResponse containing a manually defined
status code
andbody
. - an HTTPResponse_Exception. A special type of response which indicates an error. By returning the exception, the execution pipeline can adapt and display any error handlers.
app/code/controllers/TeamController.php
/**
* Return some additional data to the current response that is waiting to go out, this makes $Title set to
* 'MyTeamName' and continues on with generating the response.
*/
public function index(HTTPRequest $request)
{
return [
'Title' => 'My Team Name'
];
}
/**
* We can manually create a response and return that to ignore any previous data.
*/
public function someaction(HTTPRequest $request)
{
$this->setResponse(new HTTPResponse());
$this->getResponse()->setStatusCode(400);
$this->getResponse()->setBody('invalid');
return $this->getResponse();
}
/**
* Or, we can modify the response that is waiting to go out.
*/
public function anotheraction(HTTPRequest $request)
{
$this->getResponse()->setStatusCode(400);
return $this->getResponse();
}
/**
* We can render HTML and leave SilverStripe to set the response code and body.
*/
public function htmlaction()
{
return $this->customise(new ArrayData([
'Title' => 'HTML Action'
]))->renderWith('MyCustomTemplate');
}
/**
* We can send stuff to the browser which isn't HTML
*/
public function ajaxaction()
{
$this->getResponse()->setBody(json_encode([
'json' => true
]));
$this->getResponse()->addHeader("Content-type", "application/json");
return $this->getResponse().
}
For more information on how a URL gets mapped to an action see the Routing documentation.
Security
See the Access Controller documentation.
Templates
Controllers are automatically rendered with a template that makes their name. Our TeamsController
would be rendered
with a TeamsController.ss
template. Individual actions are rendered in TeamsController_{actionname}.ss
.
If a template of that name does not exist, then SilverStripe will fall back to the TeamsController.ss
then to
Controller.ss
.
Controller actions can use renderWith
to override this template selection process as in the previous example with
htmlaction
. MyCustomTemplate.ss
would be used rather than TeamsController
.
For more information about templates, inheritance and how to render into views, See the Templates and Views documentation.
Link
Each controller should define a Link()
method. This should be used to avoid hard coding your routing in views,
as well as give other features in SilverStripe the ability to influence link behaviour.
app/code/controllers/TeamController.php
public function Link($action = null)
{
// Construct link with graceful handling of GET parameters
$link = Controller::join_links('teams', $action);
// Allow Versioned and other extension to update $link by reference.
$this->extend('updateLink', $link, $action);
return $link;
}
Connecting Pages to Controllers
By default, a controller for a page type must reside in the same namespace as its page. If you find that your controllers are in a different namespace then you'll need to overide SiteTree::getControllerName().
Example controller:
namespace App\Controller;
use SilverStripe\Control\Controller;
class TeamPageController extends Controller
{
public function getExample()
{
return 'example';
}
}
Example page:
namespace App\Page;
use App\Controller\TeamPageController;
use Page;
class TeamPage extends Page
{
public function getControllerName()
{
return TeamPageController::class;
}
}
You'd now be able to access methods of the controller in the pages template
<!-- TeamPage.ss -->
<p>{$getExample}</p>