Controllers

What is a controller?

A controller is used to manage the logic for a certain section of your application. Most commonly, controllers are used to manage the logic for a single model. For example, if you were building a site that manages a video collection, you might have a VideosController and a RentalsController managing your videos and rentals, respectively. In Cake, controller names are always plural.

Your application’s controllers are classes that extend the Cake AppController class, which in turn extends a core Controller class. Controllers can include any number of actions: functions used in your web application to display views.

The AppController class can be defined in /app/app_controller.php and it should contain methods that are shared between two or more controllers. It itself extends the Controller class which is a standard Cake library.

An action is a single functionality of a controller. It is run automatically by the Dispatcher if an incoming page request specifies it in the routes configuration. Returning to our video collection example, our VideosController might contain the view(), rent(), and search() actions. The controller would be found in /app/controllers/videos_controller.php and contain:

<?php
class VideosController extends AppController
{
    function view($id)
    {
        //action logic goes here..
    }

    function rent($customer_id, $video_id)
    {
        //action logic goes here..
    }

    function search($query)
    {
        //action logic goes here..
    }
}

You would be able to access these actions using the following example URLs:

http://www.example.com/videos/view/253
http://www.example.com/videos/rent/5124/0-235253
http://www.example.com/videos/search/hudsucker+proxy

But how would these pages look? You would need to define a view for each of these actions - check it out in the next chapter, but stay with me: the following sections will show you how to harness the power of the Cake controller and use it to your advantage. Specifically, you’ll learn how to have your controller hand data to the view, redirect the user, and much more.

Controller Functions

While this section will treat most of the often-used functions in Cake’s Controller, it’s important to remember to use https://api.cakephp.org for a full reference.

Interacting with your Views

  • set

  • string $var

  • mixed $value

This function is the main way to get data from your controller to your view. You can use it to hand over anything: single values, whole arrays, etc. Once you’ve used set(), the variable can be accessed in your view: doing set(‘color’, ‘blue’) in your controller makes $color available in the view.

  • validateErrors

Returns the number of errors generated by an unsuccessful save.

  • validate

Validates the model data according to the model’s validation rules. For more on validation, see Chapter “Data Validation”.

  • render

  • string $action

  • string $layout

  • string $file

You may not often need this function, because render is automatically called for you at the end of each controller action, and the view named after your action is rendered. Alternatively, you can call this function to render the view at any point in the controller logic.

User Redirection

  • redirect

  • string $url

Tell your users where to go using this function. The URL passed here can be a Cake internal URL, or a fully qualified URL (http://…).

  • flash

  • string $message

  • string $url

  • int $pause

This function shows $message for $pause seconds inside of your flash layout (found in app/views/layouts/flash.thtml) then redirects the user to the specified $url.

Cake’s redirect() and flash() functions do not include an exit() call. If you wish your application to halt after a redirect() or flash(), you’ll need to include your own exit() call immediately after. You may also want to return rather than exit(), depending on your situation (for example, if you need some callbacks to execute).

Controller Callbacks

Cake controllers feature a number of callbacks you can use to insert logic before or after important controller functions. To utilize this functionality, declare these functions in your controller using the parameters and return values detailed here.

  • beforeFilter

Called before every controller action. A useful place to check for active sessions and check roles.

  • afterFilter

Called after every controller action.

  • beforeRender

Called after controller logic, and just before a view is rendered.

Other Useful Functions

While these are functions part of Cake’s Object class, they are also available inside the Controller:

  • requestAction

    • string $url

    • array $extra

This function calls a controller’s action from any location and returns the rendered view. The $url is a Cake URL (/controllername/actionname/params). If the $extra array includes a ‘return’ value, AutoRender is automatically set to true for the controller action.

You can use requestAction to get data from another controller action, or get a fully rendered view from a controller.

First, getting data from a controller is simple. You just use requestAction in the view where you need the data:

<?php
// Here is our simple controller:

class UsersController extends AppController
{
    function getUserList()
    {
        return $this->User->findAll();
    }
}

Imagine that we needed to create a simple table showing the users in the system. Instead of duplicating code in another controller, we can get the data from UsersController::getUserList() instead by using requestAction():

<?php
class ProductsController extends AppController
{
    function showUserProducts()
    {
        $this->set('users', $this->requestAction('/users/getUserList'));

        // Now the $users variable in the view will have the data from
        // UsersController::getUserList().
    }
}

If you have an often used element in your application that is not static, you might want to use requestAction() to inject it into your views. Let’s say that rather than just passing the data from UsersController::getUserList, we actually wanted to render that action’s view (which might consist of a table), inside another controller. This saves us from duplicating view code:

<?php
class ProgramsController extends AppController
{
    function viewAll()
    {
        $this->set('userTable', $this->requestAction('/users/getUserList', array('return')));

        // Now, we can echo out $userTable in this action's view to
        // see the rendered view that is also available at /users/getUserList.
    }
}

Please note that actions called using requestAction() are rendered using an empty layout - this way you don’t have to worry about layouts getting rendered inside of layouts.

The requestAction() function is also useful in AJAX situations where a small element of a view needs to be populated before or during an AJAX update.

  • log

    • string $message

    • int $type = LOG_ERROR

You can use this function to log different events that happen within your web application. Logs can be found inside Cake’s /tmp directory.

If the $type is equal to the PHP constant LOG_DEBUG, the message is written to the log as a debug message. Any other type is written to the log as an error:

<?php
// Inside a controller, you can use log() to write entries:
$this->log('Mayday! Mayday!');
//Log entry:
06-03-28 08:06:22 Error: Mayday! Mayday!
$this->log("Looks like {$_SESSION['user']} just logged in.", LOG_DEBUG);
//Log entry:
06-03-28 08:06:22 Debug: Looks like Bobby just logged in.
  • postConditions

    • array $data

A method to which you can pass $this->data, and it will pass back an array formatted as a model conditions array.

For example, if I have a person search form:

// app/views/people/search.thtml:
<?php echo $html->input('Person/last_name'); ?>

Submitting the form with this element would result in the following $this->data array:

Array
(
    [Person] => Array
        (
            [last_name] => Anderson
        )
)

At this point, we can use postConditions() to format this data to use in model:

<?php
// app/controllers/people_controller.php:
$conditions = $this->postConditions($this->data);

// Yields an array looking like this:
Array
(
    [Person.last_name] => Anderson
)

// Which can be used in model find operations:
$this->Person->findAll($conditions);

Controller Variables

Manipulating a few special variables inside of your controller allows you to take advantage of some extra Cake functionality:

$name

PHP 4 doesn’t like to give us the name of the current class in CamelCase. Use this variable to set the correct CamelCased name of your class if you’re running into problems.

$uses

Does your controller use more than one model? Your FragglesController will automatically load $this->Fraggle, but if you want access to $this->Smurf as well, try adding something like the following to your controller:

<?php
var $uses = array('Fraggle','Smurf');

Please notice how you also need to include your Fraggle model in the $uses array, even though it was automatically available before.

$helpers

Use this variable to have your controller load helpers into its views. The HTML helper is automatically loaded, but you can use this variable to specify a few others:

<?php
var $helpers = array('Html','Ajax','Javascript');

Remember that you will need to include the HtmlHelper in the $helpers array if you intend to use it. It is normally available by default, but if you define $helpers without it, you’ll get error messages in your views.

$layout

Set this variable to the name of the layout you would like to use for this controller.

$autoRender

Setting this to false will stop your actions from automatically rendering.

$beforeFilter

If you’d like a bit of code run every time an action is called (and before any of that action code runs), use $beforeFilter. This functionality is really nice for access control - you can check to see a user’s permissions before any action takes place. Just set this variable using an array containing the controller action(s) you’d like to run:

<?php
class ProductsController extends AppController
{
    var $beforeFilter = array('checkAccess');

    function checkAccess()
    {
        //Logic to check user identity and access would go here....
    }

    function index()
    {
        //When this action is called, checkAccess() is called first.
    }
}

$components

Just like $helpers and $uses, this variable is used to load up components you will need:

<?php
var $components = array('acl');

Controller Parameters

Controller parameters are available at $this->params in your Cake controller. This variable is used to get data into the controller and provide access to information about the current request. The most common usage of $this->params is to get access to information that has been handed to the controller via POST or GET operations.

$this->data

Used to handle POST data sent from HTML Helper forms to the controller:

<?php
// A HTML Helper is used to create a form element

$html->input('User/first_name');

// When rendered as HTML it looks like:

<input name="data[User][first_name]" value="" type="text" />

// And when submitted to the controller via POST,
// shows up in $this->data['User']['first_name']

Array
(
    [data] => Array
        (
            [User] => Array
                (
                    [username] => mrrogers
                    [password] => myn3ighb0r
                    [first_name] => Mister
                    [last_name] => Rogers
                )

        )
)

$this->params[‘form’]

Any POST data from any form is stored here, including information also found in $_FILES.

$this->params[‘bare’]

Stores ‘1’ if the current layout is bare, ‘0’ if not.

$this->params[‘ajax’]

Stores ‘1’ if the current layout is ajax, ‘0’ if not.

$this->params[‘controller’]

Stores the name of the current controller handling the request. For example, if the URL /posts/view/1 was called, $this->params[‘controller’] would equal “posts”.

$this->params[‘action’]

Stores the name of the current action handling the request. For example, if the URL /posts/view/1 was called, $this->params[‘action’] would equal “view”.

$this->params[‘pass’]

Stores the GET query string passed with the current request. For example, if the URL /posts/view/?var1=3&var2=4 was called, $this->params[‘pass’] would equal “?var1=3&var2=4”.

$this->params[‘url’]

Stores the current URL requested, along with key-value pairs of get variables. For example, if the URL /posts/view/?var1=3&var2=4 was called, $this->params[‘url’] would look like this:

[url] => Array
        (
            [url] => posts/view
            [var1] => 3
            [var2] => 4
        )