Frontcontroller

1. Introduction

The front controller is - along with the Pagecontroller - another central integral part of the adventure php framework. Basic to this implementation are the definition of the front controller pattern of Martin Fowler and the java sources of the java application framework struts. To go further into this topic please visit the PHP patterns website (German).

The front controller component used in this application framework is a singleton instance of the FrontController class, takes the command given in the users' requests and executes the actions existing for the effective application. There are several kinds of actions that are executed according to the timing model described in the following diagram:

Frontcontroller timing model

In common, action types containing the "pre" keyword are execuded before a specific task, action types that contain the "post" keyword are execued after a defined step. The "prepagecreate" actions often are taken to create the application's model, "posttransform" actions merely are used to to things like logging. To implement front controller actions the framework contains two abstract implementations that serve as basis for concrete implementations for actions (AbstractFrontcontrollerAction) and their information (FrontcontrollerInput). The FrontControllerInputFilter is designed to extract the action commands out of the url so that the front controller can execute them. This component the developers does not get in contact with in common, because the front controller executes it internally itself. In order to have actions, that are executed at each request, the developer can register these actions to the front controller in the central index.php file. These act like normal actions concering the timing model. The following UML diagramm shows the front controller components altogether:

Frontcontroller Actions Inputs UML

2. Implementation

Software written in front controller style merely contain two areas. For a start action and input classes must be written that inherit from AbstractFrontcontrollerAction and FrontcontrollerInput, further, a configuration that describes the action must be built.


2.1. Action and input classes

Classes that are descended from the abstract action and input classes encapsulate the functionality of an action. As it is described in the API documentation an action class must implement the run() method, because this function is execuded for each action during dispatching. An input class is a data class that contains the model information of the action. In a simple application, the input object of an front controller action can form the model concurrently. The code example printed after this passage shows two simple action an input classes:
PHP-Code
class DemoAction extends AbstractFrontcontrollerAction { function DemoAction(){ } function run(){ echo 'I am front controller action class! My name is '. $this->__Input->getAttribute('Name').'!'; } } class DemoInput extends FrontcontrollerInput { function DemoInput(){ $this->__Attributes['Name'] = 'James Blunt'; } }
If this action is executed, the output shows the sentence
APF-Template
I am front controller action class! My name is James Blunt!
Due to the fact that actions know the context of the entire application, actions can be used to encapsulate various parts of an application if reasonable. A popular example is user authentication. This can be achieved by checking the user's credentials in a "prepagecreate" action and set the parameters of the application to the desired valued.

Note: Within an action it is easy to access the input object via the $__Input variable. If you have to access an action's input from outside the action, you can use the getInput() method. This function returns the action's input as a reference.


2.2. Configuration

Each action must be defined within a configuration file. This file must contain the namespace to the action and input classes, the file name of the classes and the class names itself. Configuration files must be stored under the directory that can be defined by the expression
APF-Template
{ActionNamespace}::actions::{CONTEXT}
The name of the configuration file can be described by
APF-Template
{ENVIRONMENT}_actionconfig.ini
{ENVIRONMENT} must be replaced by the current value of the environment variable stored in the registry. By default, this valus must be replaced with DEFAULT. Each file can contain one or more action definitions for actions, that belong to the same namespace.
APF-Template
[{ActionName}] FC.ActionNamespace = "" FC.ActionFile = "" FC.ActionClass = "" FC.InputFile = "" FC.InputClass = "" FC.InputParams = ""
Besides, the performed parameters have the following meanings:
  • ActionName:
    Name of the action. This name must be present in the URL if the defined action should be called (Example: setModel).
  • FC.ActionNamespace:
    Namespace of the action's configuration file (Example: sites::demosite::biz::actions).
  • FC.ActionFile:
    Name of the file that contains the action class implementation (Example: LoadModelAction).
  • FC.ActionClass:
    Name of the action class (Example: LoadModelAction).
  • FC.InputFile:
    Name of the file, the input class resides (Example: DemositeModel).
  • FC.InputClass:
    Name of the input class (Example: DemositeModel).
  • FC.InputParams:
    Configuration directive that defines the start parameters of an input object. This is often used to configure a specific action for the use in a specific application without changing the source code. (Example: login:true|headview:menu. Key and value are separated by ":", different pairs by "|").
Due to the fact, that front controller actions are part of the business layer the code files should be placed under the biz folder of an module or application. In common the developer creates a subfolder named actions to store these files and to generate more clarity. Since namespace and name of the class files can be choosen freely the developer faces no restictions.


2.3. Changes to the index.php

To operate an application in front controller style the index.php file must contain the following lines of code:
PHP-Code
// create an instance of the front controller $fC = &Singleton::getInstance('Frontcontroller'); // set the context of the application $fC->set('Context','sites::demosite'); // set the desired standard language $fC->set('Language','de'); // generate the specified site $fC->start('sites::demosite::pres::templates','website');
If desired the developer can register "permanent" actions by
PHP-Code
// register action "Login" $fC->registerAction('sites::demosite::biz','Login');
before the execution of the start() methode. Now it is possible to execute any actions in applications or modules.


In order to generate links as easy as within page controller applications the component FrontcontrollerLinkHandler was introduced. This class can be used to manipulate existing URLs or create new URLs.

This behaviour is only activated, if the constructor of the desired action contains the assignment of the value true to the $__KeepInURL class member. By default, the value is false. If not set to true, all action instructions are removed from the generated URL. This adds the possibility to have more than one action definition in one URL and so create complex programms.

The following example shows how the FrontcontrollerLinkHandler can be used. To keep things simple the links will be descussed in rewrite mode only. Manipulating "normal" URLs is similar.

The link schema of a front controller action instruction within the url is
APF-Template
{namespace}-action:{name}={key1}:{value1}|{key2}:{value2}|...
for normal urls and
APF-Template
/{namespace}-action/{name}/{key1}/{value1}/{key2}/{value2}/...
for rewrite urls. With normal urls, & or ? is used as a separator between parameters and action instructions, with rewrite urls, you have to use /~/.


2.4.1. Simple manipulation of parameters
In many applications it is necessary to generate dynamic links. Within front controller based applications where no dynamic URLs are necessary the LinkHandler can be used instead of the FrontcontrollerLinkHandler component. But it is recommended to use the the latter to be secure. To change the link
APF-Template
http://adventure-php-framework.org/Page/Home/benchmarkreport/true/param1/value1/param2/value2
to the link
APF-Template
http://adventure-php-framework.org/Page/Guestbook/benchmarkreport/true
in an easy way, the following code fragment can be used:
PHP-Code
// define URL $URL = 'http://adventure-php-framework.org/Page/ChangeLog/benchmarkreport/true/param1/value1/param2/value2'; // define changes $ChangeParams = array( 'Page' => 'Guestbook', 'param1' => '', 'param2' => '' ); echo FrontcontrollerLinkHandler::generateLink($URL,$ChangeParams);

2.4.2. Manipulation of parameters and actions
Action definitions are treated as "normal" URL parameters as well. Thus is low-end to change the URL
APF-Template
http://adventure-php-framework.org/Page/ChangeLog/benchmarkreport/true/param1/value1/param2/value2
to
APF-Template
http://adventure-php-framework.org/Page/Guestbook/benchmarkreport/true/param1/value1/param2/value2/~/ modules_guestbook_biz-action/LoadEntryList/pagesize/20/pager/false/adminview/true
In this case the following parameter array was given to the generateLink methode:
PHP-Code
// define URL $URL = 'http://adventure-php-framework.org/Page/ChangeLog/benchmarkreport/true/param1/value1/param2/value2'; // define changes to the URL $ChangeParams = array( 'modules_guestbook_biz-action:LoadEntryList' => 'pagesize:20|pager:false|adminview:true', 'Page' => 'Guestbook' ); // generate link echo FrontcontrollerLinkHandler::generateLink($URL,$ChangeParams);
If the desired action was added as a "permanent" action it is only necessary to call the FrontcontrollerLinkHandler without a second parameter. In doing so all actions that have configured $__KeepInURL to true will be contained in the URL definition.


2.4.3. Manipulation of parameters and actions with help of generateURLParams()
The example in chapter 1.4.2 has the disadvantage, that the developer must be aware of the syntax of a frontcontroller URL. To make generation of front controller URLs more comfortable, the FrontcontrollerLinkHandler features the method generateURLParams. This function can generate an action parameter array for use with the generateLink() method. Generation goes as follows:
PHP-Code
// define URL $URL = 'http://adventure-php-framework.org/Page/ChangeLog/benchmarkreport/true/param1/value1/param2/value2'; // define URL changes $ChangeParams = array( 'Page' => 'Guestbook' ); // Parameter der FrontController-Action erzeugen $ChangeParams = array_merge( $ChangeParams, FrontcontrollerLinkHandler::generateURLParams( 'modules::guestbook::biz', 'LoadEntryList', array( 'pagesize' => '20', 'pager' => 'false', 'adminview' => 'true' ) ) ); // generate link echo FrontcontrollerLinkHandler::generateLink($URL,$ChangeParams);
Owing to performance issues this method should not be used excessively. One generation commonly consumes about 0.004 sec to generate the parameter array. If the operation mode concerning the url style is clear, the URLs should be generated as described in chapter 1.4.2.


2.5. Timing model

The FrontController has it's own timing model that enables the developer to influence at which point of time the action is executed. The time can be defined the class attribute $__Type of the AbstractFrontcontrollerAction class. This value is prepagecreate by default. There are four modes defined:
  • prepagecreate: Action is executed before the page object is created an the DOM tree is created.
  • postpagecreate: Action is executed after the creation of the page controller page.
  • pretransform: Action is executed before transforming the page controller page.
  • posttransform: Action is executed after transforming the page controller page.
To define the right mode of your action, please define your action class as follows:
PHP-Code
class MyAction extends AbstractFrontcontrollerAction { // set timing var $__Type = 'pretransform'; function MyAction(){ } function run(){ } }
Details for the function run() can be seen in the API documentation of the class Frontcontroller.


2.6. Model based view concept

In contrast to page controller applications, the front controller allows to instanciate the business layer before the presentation tier. This holds the advantage to use the business layer to control the presentation tier, in particular, the views or the content of the views of an application.

To rip this advantage off in GUI design the XML taglib fcon_taglib_importdesign was introduced. This component includes views, that are defined within an application model, that is filled by front controller actions. In common the developer can create a independent business class like this:
PHP-Code
class DemoSiteModel extends coreObject { function DemoSiteModel(){ $this->__Attributes['view.content.template'] = 'login'; $this->__Attributes['view.topmenu.template'] = 'empty'; } }
Filling the attributes can be achieved by getting reference on this class by
PHP-Code
$Model = &$this->__getServiceObject('sites::demosite::biz','DemoSiteModel');
By adding the XML tag
APF-Template
<fcon:importdesign templatenamespace="sites::apfdocupage::pres::templates" modelnamespace="sites::demosite::biz" modelfile="DemoSiteModel" modelclass="DemoSiteModel" modelparam="view.content.template" [sessionsingleton="true|false"] />
to a template file a view depending on the model's parameters can be included. To use the tag it must be announced using the
APF-Template
<core:addtaglib namespace="tools::html::taglib" prefix="fcon" class="importdesign" />
directive. The sessionsingleton attribute defines, whether the model class is created in SESSIONSINGLETON or in SINGLETON mode. Details on the object creation can be taken from the API documentation of the ServiceManager class.

With this concept views can easily be included by model information and the GUI can be controlled by the business layer completely. Moreover this is more flexible compared with the page controller as a single responsible entity.


Comments

Do you want to add a comment to the article above, or do you want to post additional hints? So please click here. Comments already posted can be found below.
There are no comments belonging to this article.