Workshop - week 02
Main Page >> Web Frameworks >> Web Frameworks - Workbook >> Workshop - week 02
Setting Up Our Default Controller
Create an Action Controller
In Zend Framework's MVC implementation, both the default action controller and the default action are named 'index'. You should therefore set up the default action controller by creating application/controllers/IndexController.php with the following contents:
<?php // application/controllers/IndexController.php /** * IndexController is the default controller for this application * * Notice that we do not have to require 'Zend/Controller/Action.php', this * is because our application is using "autoloading" in the bootstrap. * * @see http://framework.zend.com/manual/en/zend.loader.html#zend.loader.load.autoload */ class IndexController extends Zend_Controller_Action { /** * The "index" action is the default action for all controllers. This * will be the landing page of your application. * * Assuming the default route and default router, this action is dispatched * via the following urls: * / * /index/ * /index/index * * @return void */ public function indexAction() { /* There is nothing inside this action, but it will still attempt to render a view. This is because by default, the front controller uses the ViewRenderer action helper to handle auto rendering In the MVC grand scheme of things, the ViewRenderer allows us to draw the line between the C and V in the MVC. Also note this action helper is optional, but on default. */ } }
Because we're using the standard router, requests for http://mi-linux.wlv.ac.uk/~YourStudentNumber/QuickStart/public will be routed to the indexAction method on the IndexController action controller, as will requests to http://http://mi-linux.wlv.ac.uk/~YourStudentNumber/QuickStart/public/index and http://mi-linux.wlv.ac.uk/~YourStudentNumber/QuickStart/public/index/index.
For further information on Zend routes and routers, check out the following: http://framework.zend.com/manual/en/zend.controller.router.html
Controller and Action Name Conventions
To work correctly with the standard router, action method names should follow the lowerCamelCase convention with the suffix 'Action'. Action controller classes, on the other hand, should follow the UpperCamelCase convention with the suffix 'Controller'. While the standard router should work for almost all applications, routing in Zend Framework is completely customizable. See the Reference Guide for details.
It may seem like indexAction() is doing nothing at all, but again Zend Framework is doing useful things for you behind the scenes. In this case it is routing the request to the appropriate view to return the correct response. Unless otherwise configured, the view it will look for is views/scripts/index/index.phtml, where the views directory is contained in the same folder as the controllers directory you passed to Zend_Controller_Front::run(). The file extension for views is yet another best practice recommended for Zend Framework applications; since view templates look suspiciously like PHP scripts in ZF, it is easier to distinguish view templates from other PHP files if you use the .phtml extension instead of .php.
Let's create the view script now with the following contents:
<? // application/views/scripts/index/index.phtml ?> <h1 align="center"> Hello, Zend Framework MVC! </h1>
Create an Error Controller & View
Because of the change we made by making all requests return the default view, essentially we remove the need for the ErrorHandler that is handling EXCEPTION_NO_CONTROLLER. However, it is good practice to set up the respective error handlers, and so we will continue.
The last things you want to display to an end user of your site are either a blank page or exceptions. Zend Framework's MVC provides an ErrorHandler plugin that will detect exceptions and dispatch an ErrorController so that you can easily display appropriate content to your end user.
Additionally, you need some way to handle 404 errors- i.e., situations when the action or controller are not found.
In development, you do want to see exceptions, however. Fortunately, ZF MVC can accomodate both situations.
The ErrorHandler plugin by default will dispatch the errorAction() of the ErrorController. Let's build our controller.
<?php // application/controllers/ErrorController.php /** * ErrorController */ class ErrorController extends Zend_Controller_Action { /** * errorAction() is the action that will be called by the "ErrorHandler" * plugin. When an error/exception has been encountered * in a ZF MVC application (assuming the ErrorHandler has not been disabled * in your bootstrap) - the Errorhandler will set the next dispatchable * action to come here. This is the "default" module, "error" controller, * specifically, the "error" action. These options are configurable. * * @see http://framework.zend.com/manual/en/zend.controller.plugins.html * * @return void */ public function errorAction() { // Ensure the default view suffix is used so we always return good // content $this->_helper->viewRenderer->setViewSuffix('phtml'); // Grab the error object from the request $errors = $this->_getParam('error_handler'); // $errors will be an object set as a parameter of the request object, // type is a property switch ($errors->type) { case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER: case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION: // 404 error -- controller or action not found $this->getResponse()->setHttpResponseCode(404); $this->view->message = 'Page not found'; break; default: // application error $this->getResponse()->setHttpResponseCode(500); $this->view->message = 'Application error'; break; } // pass the environment to the view script so we can conditionally // display more/less information $this->view->env = $this->getInvokeArg('env'); // pass the actual exception object to the view $this->view->exception = $errors->exception; // pass the request to the view $this->view->request = $errors->request; } }
The above may seem a bit esoteric.
First, the ErrorHandler plugin stores error information- including the error type, exception caught, and the request that produced it- within a token that is passed in the request. We store that in the $errors variable.
Second, we do some switching based on the exception type. There are two types of exceptions that represent 404 errors: controller not found and action not found. For these, we change the HTTP response code to 404 to indicate this. All other exceptions are considered application exceptions, and we'll return the appropriate HTTP response code for these- 500.
Third, remember the env variable you passed to the front controller in the bootstrap file? We're going to get that from the front controller and pass it to the view. More on this later.
Finally, we pass the exception and request to the view.
Let's look at the related view script, which we'll place in application/views/scripts/error/error.phtml.
<? // application/views/scripts/error/error.phtml ?> <h1>An error occurred</h1> <h2><?= $this->message ?></h2> <? if ('development' == $this->env): ?> <h3>Exception information:</h3> <p> <b>Message:</b> <?= $this->exception->getMessage() ?> </p> <h3>Stack trace:</h3> <pre><?= $this->exception->getTraceAsString() ?>
Request Parameters:
<? var_dump($this->request->getParams()) ?>
<? endif ?>
We're now using the env variable in the view script to determine whether or not to display exception information. In development, you'll get all the information for debugging. Changing the value in your bootstrap.php file will prevent this sensitive information from being displayed, while providing a reasonable error message to your end user.
References
All work relating to the QuickStart tutorial is © 2006 - 2009 by Zend Technologies Ltd. All rights reserved.