Development - Controllers and Actions
- General Info
- Implementation of the Action logic
- Receiving parameters in Action
- Rendering in Controllers (passing data to the View)
- Redirecting to another URL
General Info ¶
The "Controller" layer, as it defined in MVC represents two thinner layers in a framework: controllers and actions. (The "Controller" layer also includes the main dispatcher script and the request routing system, though they are not directly involved in application development.)Controller is just a part of web application which is used to handle user requests. It is where an application "determines", which blocks the resulting web page should consist of. In complex applications, for better source code readability, it is reasonable to split the page generation logic into several parts. Each such part (responsible for generation of a single informational block on a page) is called an action.
Example of controllers:
UserController, AccountController, PageController, etc.Ussually, Controller has more than one Action and may implement also some internal logic, that is not related to Actions. Example of acceptable controller class:
<?php class AccountController extends CController { // Default constructor public function __construct() { parent::__construct(); } // Used to define access rules to controller // This method should be overridden protected function _accessRules() { return array( //array('allow', 'actions' => array('*'), 'ips' => array('127.0.0.1')), //array('deny', 'actions' => array('*'), 'ips' => array('127.0.0.2')) ); } // Default action public function indexAction() { $this->redirect('account/manage'); } // Manage action public function manageAction() { ... } // Delete action public function deleteAction() { ... } // Protected method (not action) protected function _protectedMethod() { ... } // Private method (not action) private function _privateMethod() { ... } }
Action is a part of an application that responsible for generating a certain portion of the resulting HTML code. It may be either entire web page or just a part of it. An action is always called from within a controller. When processing a user request, a controller determines which actions must be called for generation of a specific web page and proceeds to calling them one by one. Very often, when there is only one dynamically generated fragment on a page (i.e. the result of execution of a certain action), a controller has only one task: to call the single available action. The framework offers the so-called default controller which is executed, if no specific controller for a user request has been found, yet the action class matching the routing system instructions exists.
Example of actions:
Users/Edit, Pages/View, Pages/Edit, etc.
Implementation of the Action logic ¶
The general operating logic of most simple actions works according to the following scheme: retrieve data from the model and pass them to the template engine to be displayed in the user browser.Some types of HTTP requests may contain instructions for execution of actions which are not expected to generate any useful content (web page). Execution of such actions may result in redirecting a user to another URL; e.g., after deletion of a record or when data submitted via a web form have been saved on the server. In such cases the entire logic is implemented in a controller and no individual actions are necessary.
Receiving parameters in Action ¶
Since version 0.1.0, ApPHP Framework supports automatic action parameter binding. That means a controller action method can define named parameters which values will be automatically populated from global$_GET
array.
To demostrate how this works, let's assume that we need to create some action for
PagesController
.
The action requires two parameters:
- category - an integer indicating the category ID;
- language: a string indicating the language code.
$_GET
:
<?php class PostsController extends CController { public function actionCreate() { $category = ''; if(isset($_GET['category'])){ $category = (int)$_GET['category']; } $language = ''; if(isset($_GET['language'])){ $language = $_GET['language']; } // Other code starts here ... } }We can also use framework
Request
component to get the code more readable:
<?php class PostsController extends CController { public function actionCreate() { $category = A::app()->getRequest()->getQuery('category'); $language = A::app()->getRequest()->getQuery('language'); // Short format $category = A::app()->request()->post('category'); $language = A::app()->request()->get('language'); // Other code starts here ... } }Now using the action parameter feature, we can achieve this task in a more pleasant way:
<?php class PostsController extends CController { /** * URL: post/action/category/1/language/en */ public function actionCreate($category, $language='en') { $category = (int)$category; // Other code starts here ... } }Notice that we add two parameters to the action method actionCreate. The recommended way is to use the exactly names for parameters in
$_GET
. The $language
parameter takes a default value en in case
the request does not include such a parameter. Because $category does not have a default value, if the request
does not include a category parameter, so nothing will be passed to this action.
Remember: you may define/re-define URL (incliding parameters)
with routing feature of application and modules.
Rendering in Controllers - passing data to the View (template engine) ¶
When generating the HTML code of the resulting web page, the view (template engine) processes the data received from the action. Data should be passed to the template engine using the following syntax:$this->_view->text = 'some text here...'; /* sample 1 - full syntax */ $this->_view->render('controller/view'); /* sample 2 - short syntax, missing controller means use current controller name */ $this->_view->render('view'); /* sample 3 partial rendering - for AJAX calls (2nd parameter $isPartial = true) */ $this->_view->render('view', true); /* sample 4 partial rendering with returned content - for some specific methods (2nd parameter $isPartial = true, 3rd parameter $return = true) */ $result = $this->_view->render('view', true, true);Read more...
Example of an action class showing how data received from the model are passed to the view file:
<?php class AccountController extends CController { public function indexAction() { // Create a model instance to retrieve data from the DB $model = new Accounts(); // Retrieve all records from DB $records = $model->fetchAll(); // Assign data to the view variables $this->_view->records = $records; $this->_view->title = 'Account Management'; // Pass prepared data to the view file $this->_view->render('accounts/index'); } public function viewAction() { // Example of working with active record $model = Accounts::model()->findByPk(10); $model->fieldA = 'new name'; $model->fieldB = 'new type'; $model->save(); // Pass prepared data to the view file $this->_view->render('accounts/view'); } }
Redirecting to another URL ¶
Browser redirection to a different URL is carried out in controller source code using the following syntax:/* sample 1 */ $this->redirect('controller/action'); /* sample 2 */ $this->redirect('controller/action/param1/value1'); $this->redirect('controller/action/?sort_by=code&sort_dir=asc&page=1'); /* sample 3 - short syntax, missing controller means use current controller name */ $this->redirect('index'); /* sample 4 - full path */ $this->redirect('https://www.apphp.com', true); /* sample 5 - full path with redirect code */ $this->redirect('https://www.apphp.com', true, 301);