Skip to content
dbald edited this page Sep 16, 2010 · 4 revisions

Controllers

Home > Controllers

Controllers act as a grouping for views but they also define views and hold all of the main code that needs to be processed to make up your project. Controllers are possibly the most important part of your project and have many abilities to make working with your project easier.

<?php
/* Basic controller setup */
class Main_Controller extends ApplicationController_Controller {
	public function __construct() {
		// construct code
	}
	
	public function index() {
		// view code
	}
}
?>

Any method in a controller is considered a view to the framework which means that you can visit it in the browser. There are many instances that you wouldn’t want that to happen. For instance you might have created a method in the controller to return true or false if there are child pages to the current page. Being able to visit our child page check function would cause an error as well as potentially making your project run sensitive code when it shouldn’t. In order to have a method in a controller not seen as a valid view you would add an underscore to the beginning of the method name. This method of defining methods that are not views is reflected in all the controller method calls shown in the sections ahead.

Filters

Filters in controllers are a nice feature to have code executed at a specified schedule for any view in the controller. As an example you could use filters to check that someone is logged in and if not direct them to another page or throw an error before the view is even run. Filters can be set up anywhere in a controller but it is recommended to set them up in the construct method of a controller as that will make sure that the filter will be run at the correct schedule.

The available filter schedules are (Listed in the order in which they are run):

  • Page.before
  • View.before
  • View.content.before
  • View.content.after
  • View.after
  • Layout.before
  • Layout.after
  • Page.after
  • Page.output.before
  • Page.output.after

Any filters run using the View.after schedule and after would have access to the generated view content if the filter is run in the scope of the controller as shown bellow. If you are wanting to make changes to the view content before it is merged with the layout then the only schedules that have access to that are View.after and Layout.before.

<?php
/* Get the generated view content */
$this->_getViewContent();

/* Set the view content */
$this->_setViewContent("New Content");
?>

Any filters run using the Layout.after schedule and after would have access to the full generated page content if the filter is run in the scope of the controller as shown bellow. If you are wanting to make changes to the full page content before it is output to the browser then the only schedules that will be able to do that are Layout.after, Page.after, and Page.output.before.

<?php
/* Get the full page content */
$this->_getFullPageContent();

/* Set the full page content */
$this->_setFullPageContent("New Content");

When setting up a filter you have 3 different filter types to choose from:
/* addFilterAll which is used to set up a filter for every view in the controller */
$this->_addFilterAll('Filter Method', 'Schedule');

/* addFilterOn which is used to setup a filter on just specific views */
$this->_addFilterOn('Filter Method', array('View'), 'Schedule');

/* addFilterExcept which is used to setup a filter on all views except the specified views */
$this->_addFilterExcept('Filter Method', array('View'), 'Schedule');
?>

When setting up a filter the first argument is always the method to use as the filter however this can also be filled with an array and you can use any class and method combination you want to act as the filter as shown in the example below. Also the schedule argument is optional as Page.before is assumed when no schedule is specified.

<?php
/* An example filter using a method in a helper */
$this->_addFilterAll(array('Validation_Helper', 'validateMyView'));
?>

The framework will also try to merge filters so that if you wanted you could define a filter as a filter all and then for instance remove the filter on some specific views as shown in the example below.

<?php
/* An example of filters merging */
$this->_addFilterAll(array('Validation_Helper', 'validateMyView'));
$this->_addFilterExcept(array('Validation_Helper', 'validateMyView'), array('dontFilterMe'));
?>

Sometimes it may be necessary to remove a filter all on just one view or to remove a filter totally from the controller. To do so you would use the _removeFilterOn and the _removeFilter methods as shown in the example below. The schedule argument also exists for these methods and is optional as well as it uses Page.before if left blank.

<?php
/* An example of removing a filter on specific views. */
$this->_removeFilterOnarray('Validation_Helper', 'validateMyView'), array('dontFilterMe'));

/* An example of removing a filter completely */
$this->_removeFilter(array('Validation_Helper', 'validateMyView'));
?>

Bounceback

Bounceback’s can be really powerful especially when trying to create a website that has pages that are driven, virtually, through the database. Basically a bounceback will allow you to intercept a 404 that might happen in the controller and be able to run your own code to check if based on your own rules the page exists or not. Like filters it is recommended to setup a bounceback in the construct of the controller for the best results. It is also important to note that only one bounceback can exist per controller.

<?php
/* An example of a bounceback */
$this->_setBounceBack('Check Method', 'Bounce Method');

/* An example of removing a bounceback */
$this->_removeBounceBack();
?>

Bounceback’s can also be setup using a check method that is in a different class. The example below shows how to set that up. Only the check method can exist outside of the controller the bounce method has to be a valid view in the controller.

<?php
/* An example of a bounceback using a check method in a helper */
$this->_setBounceBack(array('Validation_Helper', 'bounceCheck'), 'index');
?>

In your check method you can use whatever means you choose to check if the view trying to load is or is not a valid view just return true or false in the check function respectively. If you return true in your check then the bounceback will load the bounce view and that view will continue processing as normal. If you return false then the bounceback will throw the pre-defined error VIEW_NOT_FOUND.

Loading a View File

View files are stored in the views directory and then in the controller directory within the view folder. Typically view files are loaded automatically by the framework based on the regular naming convention. So if you have a view called lightBulbs then the framework will load the light.bulbs.php file in automatically. However there are times that you might want to load a view manually for instance you know that you want to have an edit and create form for something you are building then rather than build the form separately into both the view files you can abstract that form into one file and load that file into those views yourself. There are a couple of methods that can assist you in loading in views manually and they have some different options as outlined below.

It is important to note that both _getView and _viewExists only check and get the view file and do not check or run the view code as defined in the controller. It is possible to check if a view method exists in a controller with the _viewExists method as shown in the examples bellow but it is not yet supported to actually run the view code when you call _getView.

To load a view: (returns true if the load was successful and false if it was not.)

<?php
/* An example of loading a view. This method of loading a view assumes that the view is in the
    current controller and branch. */
$this->_getView('index');

/* In this example of loading a view, we are defining which controller to load the view from. */
$this->_getView('index', 'ProductsServices');

/* In this example of loading a view, we are defining which controller and which branch to load the
    view from. */
$this->_getView('index', 'ProductsServices', 'ContentController');

/* This example is the same as the one above except that it is defining the root structure and not
    a branch. */
$this->_getView('index', 'ProductsServices', Reg::get('System.rootIdentifier'));
?>

To check if a view exists: (returns true if the view exists and false if not)

<?php
/* An example of checking that a view exists. This method of checking a view assumes that the
    view is in the current controller and branch. */
$this->_viewExists('index');

/* In this example of checking that a view exists, we are defining which controller the view should be in. */
$this->_viewExists('index', 'ProductsServices');

/* In this example of checking that a view exists, we are defining which controller and which branch the
    view should be in. */
$this->_viewExists('index', 'ProductsServices', 'ContentController');

/* This example is the same as the one above except that it is defining the root structure and not
    a branch. */
$this->_viewExists('index', 'ProductsServices', Reg::get('System.rootIdentifier'));

/* It is also possible to check that the view method exists by specifying either boolean true or 
    string 'both' as the last argument. */
$this->_viewExists('index', true);
$this->_viewExists('index', 'ProductsServices', true);
$this->_viewExists('index', 'ProductsServices', 'ContentController', 'both');
?>

There are times when, based on the rules in your application, you will want to use the same view code with different views. If called within the view code in the controller you can use _getView to tell the controller to load a different view file other than the default one by setting the last argument of your _getView call as boolean true as shown in the examples below.

<?php
/* Examples of using _getView to override the the loading of the default view file for the current view with
    the one specified. */
$this->_getView('index', true);
$this->_getView('index', 'ProductsServices', true);
$this->_getView('index', 'ProductsServices', 'ContentController', true);
$this->_getView('index', 'ProductsServices', Reg::get('System.rootIdentifier'), true);
?>

Application Controller

The application controller is not a main part of the framework and is not required but it exists to help you as it can hold code that can be global throughout the controllers in a specific branch allowing more reusable code. With the application controller you could do something like setup a filter all in it’s construct that checks if you are logged in but then in the construct of the main controller you could add in a filter except that would allow you to not do checks on the login and logout views. Using this method you could have a filter that automatically checks all views for a valid login except for the login and logout views as the 2 filters would merge. You can also create methods in the application controller that can be used for repetitive functions that you would want easy access to in the controller.

Setting a Layout

Layouts are stored in the layouts directory in the views folder. They are basically shell’s for your views. You can load a layout individually using the _getView method and defining ‘layout’ as the controller. You may want to use _getView to load a layout if you want to split up the layout into pieces such as having a header and footer as separate files.

In order to use a layout with a view you have to set the layout in the controller so that the controller knows to load the layout when it renders the view. You can set or remove a layout anywhere in the controller as a layout might change while your code is executing but it is recommended to set a default layout for the whole controller in the construct using the methods in the examples shown below.

<?php
/* Set which layout to load. */
$this->_setLayout('tier-1');

/* Set a layout in a branch. */
$this->_setLayout('tier-1', 'ContentController');

/* Unset the currently set layout. */
$this->_removeLayout();
?>

Clone this wiki locally