A Useful Error Controller Class For Zend Framework Applications

23rd December 2008

One useful function of any application is to report on any errors that occurred. Zend Framework comes with a nice error controller system that you can activate by creating an ErrorController class.

The following is an ErrorController class that I use. It detects what sort of error occurred and displays a message to the user. It will also email a detailed report of the error to the server admins.

  1. class ErrorController extends Zend_Controller_Action
  2. {
  3. public function errorAction()
  4. {
  5. // Ensure the default view suffix is used so we always return good
  6. // content
  7. $this->_helper->viewRenderer->setViewSuffix('phtml');
  8.  
  9. // Grab the error object from the request
  10. $errors = $this->_getParam('error_handler');
  11.  
  12. switch ($errors->type) {
  13. case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER:
  14. case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION:
  15. // 404 error -- controller or action not found
  16. $this->getResponse()->setHttpResponseCode(404);
  17. $this->view->message = 'Page not found';
  18. $this->view->code = 404;
  19. if ($errors->type == Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER) {
  20. $this->view->info = sprintf(
  21. 'Unable to find controller "%s" in module "%s"',
  22. $errors->request->getControllerName(),
  23. $errors->request->getModuleName()
  24. );
  25. }
  26. if ($errors->type == Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION) {
  27. $this->view->info = sprintf(
  28. 'Unable to find action "%s" in controller "%s" in module "%s"',
  29. $errors->request->getActionName(),
  30. $errors->request->getControllerName(),
  31. $errors->request->getModuleName()
  32. );
  33. }
  34. break;
  35. case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION:
  36. default:
  37. // application error
  38. $this->getResponse()->setHttpResponseCode(500);
  39. $this->view->message = 'Application error';
  40. $this->view->code = 500;
  41. $this->view->info = $errors->exception;
  42. break;
  43. }
  44.  
  45. // send a mail to let someone know that there was a problem!
  46. $config = Zend_Registry::get('configuration');
  47. $tr = new Zend_Mail_Transport_Smtp($config->smtp);
  48. Zend_Mail::setDefaultTransport($tr);
  49.  
  50. $mail = new Zend_Mail();
  51. $emailBody = "An error occurred in the system. The error message contained the following output:\n\n";
  52. $emailBody .= $this->view->message." (".$this->view->code.")\n\n";
  53. $emailBody .= "Zend Error Type: ".$errors->type."\n\n";
  54. $emailBody .= "REQUEST_URI: ".$_SERVER['REQUEST_URI']."\n\n";
  55. if ( isset($_SERVER['HTTP_REFERER']) ) {
  56. $emailBody .= "HTTP_REFERER: ".$_SERVER['HTTP_REFERER']."\n\n";
  57. }
  58. $emailBody .= "Stack trace: \n\n". $errors->exception->getTraceAsString()."\n\n";
  59.  
  60. // find the user to blame!
  61. $username = Zend_Auth::getInstance()->getIdentity();
  62. $emailBody .= "This error was created by ".$username.".";
  63.  
  64. $mail->setBodyText($emailBody);
  65. $mail->setFrom('[email protected]', '');
  66. $mail->addTo($config->adminEmail, $config->adminName);
  67. $mail->setSubject('An Error Occured');
  68. // Email
  69. $mail->send();
  70.  
  71. $this->view->title = 'Error!';
  72. $this->view->heading = 'Error!';
  73.  
  74. // pass the environment to the view script so we can conditionally
  75. // display more/less information
  76. $this->view->env = $this->getInvokeArg('env');
  77.  
  78. // pass the actual exception object to the view
  79. $this->view->exception = $errors->exception;
  80.  
  81. // pass the request to the view
  82. $this->view->request = $errors->request;
  83. }
  84. }

This error controller relies on certain options that have been set up in your configuration file. Add the following options to your configuration file to get these options working.

  1. smtp = my.smtpserver.com
  2. adminEmail = [email protected]
  3. adminName = 'Your name'

To enable this just call the throwExceptions() function of the Zend_Controller_Front and pass it a value of false. This will cause the framework to look for an error controller rather than try to print out things.

Finally, you need to add a view so that your errors will be displayed nicely. This will display more if the environment is set to 'test'.

  1. <h3>Error has happened. Inside this application. Sorry about that.</h3>
  2. <p><?=$this->message ?> (<?=$this->code ?>) </p>
  3. <?
  4. if( $this->env == 'test' ) {
  5. if ( isset($this->info ) ) { ?>
  6. <? if ( 404 == $this->code ) { ?>
  7. <p><b>Reason:</b> <?= $this->info ?></p>
  8. <? } elseif (500 == $this->code) { ?>
  9. <p>Bad server, naughty server!<br />No donut for you!</p>
  10. <p><img src="<?=$this->baseUrl();?>/images/donut.jpg" /></p>
  11. <h4>Exception information:</h4>
  12. <p><b>Message:</b> <?= $this->info->getMessage() ?></p>
  13. <h4>Stack trace:</h4>
  14. <pre><?= $this->info->getTraceAsString() ?></pre>
  15. <? } ?>
  16. <? } ?>
  17. <? } ?>

 

Comments

Permalink
Nice! The only comment I'd make is that you probably do not want emails for most 404s; I'd personally restrict the email functionality to your 500 errors.

Matthew Weier … (Tue, 12/23/2008 - 15:12)

Permalink
Very true, but it depends on what sort of application you make. For the purposes that I made this for I wanted to know about 404 errors as these would definitely be mistakes.
Permalink
Keep working ,great job! :)

sedax (Thu, 12/25/2008 - 15:58)

Add new comment

The content of this field is kept private and will not be shown publicly.