A controller
is an instance of CController or its child class. It is
created by application when the user requests for it. When a controller
runs, it performs the requested action which usually brings in the needed
models and renders an appropriate view. An action
, at its simplest form, is
just a controller class method whose name starts with action
.
A controller has a default action. When the user request does not specify
which action to execute, the default action will be executed. By default,
the default action is named as index
. It can be changed by setting
CController::defaultAction.
Below is the minimal code needed by a controller class. Since this controller does not define any action, requesting for it would throw an exception.
class SiteController extends CController
{
}
Controllers and actions are identified by IDs. Controller ID is in the
format of path/to/xyz
which corresponds to the controller class file
protected/controllers/path/to/XyzController.php
, where the token xyz
should be replaced by actual names (e.g. post
corresponds to
protected/controllers/PostController.php
). Action ID is the action method
name without the action
prefix. For example, if a controller class
contains a method named actionEdit
, the ID of the corresponding action
would be edit
.
Note: Before version 1.0.3, the controller ID format was
path.to.xyz
instead ofpath/to/xyz
.
Users request for a particular controller and action in terms of route. A
route is formed by concatenating a controller ID and an action ID separated
by a slash. For example, the route post/edit
refers to PostController
and its edit
action. And by default, the URL
http://hostname/index.php?r=post/edit
would request for this controller
and action.
Note: By default, routes are case-sensitive. Since version 1.0.1, it is possible to make routes case-insensitive by setting CUrlManager::caseSensitive to be false in the application configuration. When in case-insensitive mode, make sure you follow the convention that directories containing controller class files are in lower case, and both controller map and action map are using keys in lower case.
Since version 1.0.3, an application can contain modules. The route for a controller action inside a module is in the format of moduleID/controllerID/actionID
. For more details, see the section about modules.
A controller instance is created when CWebApplication handles an incoming request. Given the ID of the controller, the application will use the following rules to determine what the controller class is and where the class file is located.
If CWebApplication::catchAllRequest is specified, a controller will be created based on this property, and the user-specified controller ID will be ignored. This is mainly used to put the application under maintenance mode and display a static notice page.
If the ID is found in CWebApplication::controllerMap, the corresponding controller configuration will be used to create the controller instance.
If the ID is in the format of 'path/to/xyz'
, the controller class
name is assumed to be XyzController
and the corresponding class file is
protected/controllers/path/to/XyzController.php
. For example, a controller
ID admin/user
would be resolved as the controller class UserController
and the class file protected/controllers/admin/UserController.php
.
If the class file does not exist, a 404 CHttpException will be raised.
In case when modules are used (available since version 1.0.3), the above process is slighly different. In particular, the application will check if the ID refers to a controller inside a module, and if so, the module instance will be created first followed by the controller instance.
As aforementioned, an action can be defined as a method whose name starts
with the word action
. A more advanced way is to define an action class
and ask the controller to instantiate it when requested. This allows
actions to be reused and thus introduces more reusability.
To define a new action class, do the following:
class UpdateAction extends CAction
{
public function run()
{
// place the action logic here
}
}
In order for the controller to be aware of this action, we override the actions() method of our controller class:
class PostController extends CController
{
public function actions()
{
return array(
'edit'=>'application.controllers.post.UpdateAction',
);
}
}
In the above, we use the path alias
application.controllers.post.UpdateAction
to specify that the action
class file is protected/controllers/post/UpdateAction.php
.
Writing class-based actions, we can organize an application in a modular fashion. For example, the following directory structure may be used to organize the code for controllers:
protected/ controllers/ PostController.php UserController.php post/ CreateAction.php ReadAction.php UpdateAction.php user/ CreateAction.php ListAction.php ProfileAction.php UpdateAction.php
Filter is a piece of code that is configured to be executed before and/or after a controller action executes. For example, an access control filter may be executed to ensure that the user is authenticated before executing the requested action; a performance filter may be used to measure the time spent in the action execution.
An action can have multiple filters. The filters are executed in the order that they appear in the filter list. A filter can prevent the execution of the action and the rest of the unexecuted filters.
A filter can be defined as a controller class method. The method name must
begin with filter
. For example, the existence of the
filterAccessControl
method defines a filter named accessControl
. The
filter method must be of the signature:
public function filterAccessControl($filterChain)
{
// call $filterChain->run() to continue filtering and action execution
}
where $filterChain
is an instance of CFilterChain which represents the
filter list associated with the requested action. Inside the filter method,
we can call $filterChain->run()
to continue filtering and action
execution.
A filter can also be an instance of CFilter or its child class. The following code defines a new filter class:
class PerformanceFilter extends CFilter
{
protected function preFilter($filterChain)
{
// logic being applied before the action is executed
return true; // false if the action should not be executed
}
protected function postFilter($filterChain)
{
// logic being applied after the action is executed
}
}
To apply filters to actions, we need to override the
CController::filters()
method. The method should return an array of
filter configurations. For example,
class PostController extends CController
{
......
public function filters()
{
return array(
'postOnly + edit, create',
array(
'application.filters.PerformanceFilter - edit, create',
'unit'=>'second',
),
);
}
}
The above code specifies two filters: postOnly
and PerformanceFilter
.
The postOnly
filter is method-based (the corresponding filter method is
defined in CController already); while the PerformanceFilter
filter is
object-based. The path alias application.filters.PerformanceFilter
specifies that the filter class file is
protected/filters/PerformanceFilter
. We use an array to configure
PerformanceFilter
so that it may be used to initialize the property
values of the filter object. Here the unit
property of
PerformanceFilter
will be initialized as 'second'
.
Using the plus and the minus operators, we can specify which actions the
filter should and should not be applied to. In the above, the postOnly
should be applied to the edit
and create
actions, while
PerformanceFilter
should be applied to all actions EXCEPT edit
and
create
. If neither plus nor minus appears in the filter configuration,
the filter will be applied to all actions.
Signup or Login in order to comment.