Controllers

Controllers contain methods which are executed when a route is accessed. To learn how to map a route to a controller method, see the routing documentation.

Application Controller

An application controller responds to requests from the front application. Notice that application controllers extend sa\application\controller.

<?php
use sa\application\controller;
class UserController extends controller {
/**
* Lists all users.
*/
public function index() {
// <implementation code>
}
}

Site Administrator Controller

Siteadmin controllers should be used for responding to routes that should only be accessible from Siteadmin. All routes that map to this type of controller will automatically require the user to be logged into their siteadmin dashboard.

The class saController extends controller and therefore inherits all of the behavior you would expect from a regular application controller.

By convention, all classes that extends saController should be have a Sa prefix (i.e. SaUserController instead of UserController).

<?php
use sa\application\controller;
class SaUserController extends saController {
/**
* Lists all users.
*/
public function index() {
// <implementation code>
}
}

Resource Controller

A resource controller responds to routing requests from resourceRoutes. These controllers serve assets, such as stylesheets, images, files, or javascript files which are specific to the module the controller belongs to.

Notice the resource controller extends controller, just as a regular controller. All controllers inherit the following methods: css(), js(), and img(). Therefore, all controllers are resource controllers. It is still best practice to have a dedicated controller to handle all of your module's assets. This allows both application and administrative controllers to share the same assets.

css() method will search /{module name}/src/css/ for your stylesheets.js() method will search /{module name}/src/js/ for your javascript files.img() method will search /{module name}/src/img/ for your images.

These methods can be overwritten to fetch assets from other locations on the server.

Basic Usage

To create a resource controller, simply extend controller. Your new resource controller will automatically inherit the necessary methods (mentioned in the note above) to render resources for you.

<?php
use sa\application\controller;
/**
* Responds to requests for static assets relevant to the user module.
*/
class UserResourceController extends controller {
}

Custom Resource Locations

You can change the directory where each method searches for your resources by defining custom methods, or overriding any of the existing methods.

<?php
use sa\application\controller;
/**
* Responds to requests for static assets relevant to the user module.
*/
class UserResourceController extends controller {
public function css($view)
{
// change location of css files to /stylesheets
$view = new assetView($view, static::assetLocation('stylesheets'));
$view->display();
}
public function js($view)
{
// change location of js files in /javascript
$view = new assetView($view, static::assetLocation('javascript'));
$view->display();
}
public function img($view)
{
//change location of images in /images
$view = new assetView($view, static::moduleLocation('images'));
$view->display();
}
/**
* If your module needs to access files which are outside the
* scope of css, js, or images, you can create a custom resource
* method. A resource route must be mapped to this method for this
* to work.
*/
public function docs($view) {
$view = new assetView($view, static::moduleLocation('documents'));
$view->display();
}
}

Extending Resource Controllers

Resource controllers are isolated on their own for good reason. When you extend a controller or override its IOC_NAME reference, the css() , js() , and img() methods will search the extended module's directories for assets instead of in the core module. Since your extended module likely won't have the same CSS/JS/image files as the parent module, all your assets will return a 404 response when accessed.

With this in mind, you should never extend a resource controller. Doing so will result in assets breaking in the parent module.

But can't the assets from the parent module be copied into the extended module?

...yes, but don't do this either unless you want a massive headache every time the parent module adds a new asset, rolls out a bug fix for an asset, or implements a new feature in JS a file. You'll have to copy & paste all the assets to your extended module every...single...time.

Instead, your extended module should have its own uniquely named resource controller. The module's resource routes should also be unique to avoid conflicting with the parent module's assets.

Rendering Content

View the responses documentation to learn about rendering content from a controller.

Accessing URL Parameters

URL parameters from dynamic routes are passed into the controller as method parameters. The following route contains 2 URL parameters. The first represents a user ID, the second is an invoice ID.

^/user/[0-9]/invoice/[0-9]$

These parameters are passed into the getUser() method in the same order as they were defined in the route.

<?php
class UserController extends controller {
public function getUser($userId, $invoiceId) {
// <implementation code>
}
}

Dependency Injection

URL parameters are often ID's which represent real entities in the database. It is bad practice to query the database manually from the controller method. Instead, you should add a docBlock above the method definition, which specifies the object type of the entity associated with the ID.

Don't

<?php
class UserController extends controller {
public function getUser($userId, $invoiceId) {
$user = app::$entityManager->find('saUser', $userId);
$invoice = app::$entityManager->find('invoice', $invoiceId);
// <implementation code>
}
}

Do

<?php
class UserController extends controller {
/**
* @param saUser $user
* @param Invoice $invoice
*/
public function getUser($user, $invoice) {
// <implementation code>
}
}