Zend Framework – Useful Tips

Here are some of my tips for users new to ZFW. I use these for most of my projects. Please feel free to modify them to suit your individual needs:

1. First and foremost, settle on a consistent layout for use thorughout your application. By ‘layout’, I mean a template – generally an html page with div sections for header, sidebar, body and footer (including the corresponding css/graphic files). ZFW (using Zend_Layout) can be made to ‘inject’ content into the body section. This will accomplish 2 things:

  • Uniform webpages across the application
  • Minimum repitition of code across pages (the conventional way of doing this is to have <?php include ?> directives in all pages

Use the following command in your index.php to kickstart Zend_Layout and automagically take care of inserting content within the layout.

Zend_Layout::startMvc(array(‘layoutPath’=>’../views/layouts’));

Note that the html component (layout.phtml) resides in the /views/layouts directory while the css and other images/js files should be in the .htdocs (web facing folder). So, the layout.phtml must use $this->baseUrl  while referring to the css/jpgs.

My layout.phtml contains the following lines of code:

<div id="content">
        <?php echo $this->layout()->content ?>
</div>

The Zend framework first renders the action script and associated html, injects that into the layout and displays the whole page to the user.

2. DO use a base controller class from which all your controller classes inherit. This base class should typically abstract out the most commonly used resources like database, identity, messenger etc. Here is the code that I use:

<?php
class BaseController extends Zend_Controller_Action
{
	protected $db;
	protected $auth;
	protected $messenger;

	public function init()
	{
		$this->db = Zend_Db_Table::getDefaultAdapter();
		$this->view->baseUrl = Zend_Controller_Front::getInstance()->getBaseUrl();
		$this->auth=Zend_Auth::getInstance();
		$this->messenger=$this->_helper->FlashMessenger;
	}
	public function preDispatch()
	{
		$this->view->messages = $this->messenger->getCurrentMessages();
	}
}
?>

The init() method makes the variables available to all controllers. The predispatch method creates a view variable named ‘messages’ that contain informational messages to be displayed to the user.

Once you have a base controller method, ALL your controllers should inherit from the BaseController (instead of Zend_Controller_Action). Having all the important variables available globally will make coding so much easier. Adding a user message is as simple as

$this->messenger->addMessage(‘Record has been added…’);

3. Make user of an error controller/action to display more meaningful error messages to users.

<?php
class ErrorController extends CustomControllerAction
{
    /**
     * This action handles
     * - Application errors
     * - Errors in the controller chain arising from missing
     * controller classes and/or action methods
     */
public function errorAction()
    {
        // Grab the error object from the request
        $errors = $this->_getParam('error_handler');
        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';
                $this->view->code  = 404;
                if ($errors->type == Zend_Controller_Plugin_ErrorHandler::
EXCEPTION_NO_CONTROLLER) { $this->view->info = sprintf( 'Unable to find action "%s" in controller "%s"', $errors->request->getActionName(), $errors->request->getControllerName() ); } if ($errors->type == Zend_Controller_Plugin_ErrorHandler::
EXCEPTION_NO_ACTION) { $this->view->info = sprintf( 'Unable to find action "%s" in controller "%s"
in module "%s"'
, $errors->request->getActionName(), $errors->request->getControllerName(), $errors->request->getModuleName() ); } break; default: // application error $this->view->message = 'Application error'; $this->view->code = 500; $this->view->info = $errors->exception; break; } $this->view->title = 'Error!'; $this->view->heading = 'Error!'; } } ?>

Here is the corresponding errors.phtml file

<h3>An error has occurred inside this application. Sorry about that.</h3>
<p><?php echo $this->message ?> (<?php echo $this->code ?>) </p>
<?php
 if ( isset($this->info ) )
 {
 if ( 404 == $this->code )
 { ?>
  <p><b>Reason:</b> <?php echo $this->info ?></p>
<?php } elseif (500 == $this->code) { ?>
  <p>Bad server, naughty server!<br />No donut for you!</p>
  <p><img src="<?php echo $this->baseUrl();?>/images/donut.jpg" /></p>
  <h4>Exception information:</h4>
 <p><b>Message:</b> <?php echo $this->info->getMessage() ?></p>
 <h4>Stack trace:</h4>
 <pre><?php echo $this->info->getTraceAsString() ?></pre>
<?php } ?>
<?php } ?>

Note how the errorcontroller extends our base class CustomControllerAction. This in turn makes available "$this->baseUrl" used in errors.phtml. Remember that you need to set:

$controller->throwExceptions(false);

in your index.php file. This setting will make ZF redirect to the error contoller and present a nicely formatted page to the user.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s