Jun 20: Zend Framework Exception Handling
Handling exceptions is extremely import if you want to have an application that is stable and end-user friendly. The Zend Framework comes with some great features for handling things like missing controllers and actions right out of the box. Like many things with the Zend Framework, you have to dig a little before you find the answers that you need. There are three steps needed to take advantage of the build in exception handling features:
1) You have to register the Zend_Controller_Plugin_ErrorHandler plugin.
2) You have to create an error controller
3) You have to create the templates for the specific error types
Read on to see what my versions of the above look like...
1) You have to register the Zend_Controller_Plugin_ErrorHandler plugin.
2) You have to create an error controller
3) You have to create the templates for the specific error types
Read on to see what my versions of the above look like...
First is registering the plugin. That's super easy.
For production, you probably want to turn off the front controller's abililty to throw exceptions.
Next is my error controller. By default, the Zend_Controller_Plugin_ErrorHandler looks for the error controller in your default controllers directory. Mine is located at /modules/default/controllers/ErrorController.php and looks like this:
Here are those two templates:
not-found.phtml
server-error.phtmlThat's it. In case you are wondering where all of the HTML is in those templates, I use Zend_Layout so my action-based view scripts are quite minimal.
Now you have a top level catch-all that can handle routing errors without having to write a "No Route" plugin and you get a top level exception handler in case you let one slip by you. Which would never happen of course
// Set up controller
$frontController = Zend_Controller_Front::getInstance();
$frontController->throwExceptions(true)
->registerPlugin(new Zend_Controller_Plugin_ErrorHandler());For production, you probably want to turn off the front controller's abililty to throw exceptions.
Next is my error controller. By default, the Zend_Controller_Plugin_ErrorHandler looks for the error controller in your default controllers directory. Mine is located at /modules/default/controllers/ErrorController.php and looks like this:
class ErrorController extends MDJP_Controller_Action
{
/**
* Should we display the errors?
*
* @var boolean
*/
protected $_displayErrors = true;
/**
* The error handler
*
* @var Zend_Controller_Plugin_ErrorHandler
*/
protected $_error = null;
/**
* Controller init method
*/
public function init()
{
if ($this->getInvokeArg('displayErrors') == true) {
$this->_displayErrors = true;
}
$this->_error = $this->getRequest()->getParam('error_handler');
}
/**
* Default action of the Zend_Controller_Plugin_ErrorHandler
*/
public function errorAction()
{
// Clear previous content
$this->getResponse()->clearBody();
// This method delegates to others so there is no template for it
$this->getHelper('ViewRenderer')->setNoRender();
switch ($this->_error->type) {
case 'EXCEPTION_NO_CONTROLLER':
case 'EXCEPTION_NO_ACTION':
$this->_forward('not-found');
return;
case 'EXCEPTION_OTHER':
$this->_forward('server-error');
return;
}
}
/**
* Handle a missing controller or action
*
* If displaying errors, we include the exception in the view variables
*/
public function notFoundAction()
{
$this->_response->setHttpResponseCode(404);
if ($this->_displayErrors === true) {
$this->view->ExceptionMessage = $this->_error->exception->getMessage();
}
}
/**
* Handle an unknown server error
*
* If displaying errors we pass back the exception message and the traceback
*/
public function serverErrorAction()
{
if ($this->_displayErrors === true) {
$this->view->ExceptionMessage = $this->_error->exception->getMessage();
$rawTrace = array_reverse($this->_error->exception->getTrace());
$traceback = array();
$index = 0;
foreach ($rawTrace as $traceEntry) {
$tracebackArgs = '';
if (array_key_exists('args', $traceback)) {
$tracebackArgs = implode(',', $traceback['args']);
}
$traceback[] = '#'.$index++
.' '.$traceEntry['file']
.'('.$traceEntry['line'].')'
.' '.$traceEntry['class'].$traceEntry['type'].$traceEntry['function'].'('.$tracebackArgs.')';
}
$this->view->Traceback = print_r(implode("\n", $traceback), TRUE);
}
// Always log errors
$exception = $this->_error->exception;
error_log($exception);
$this->_response->setHttpResponseCode(500);
}
}So the plugin will forward to the error action of your ErrorController. In there you can do anything you want, I choose to handle the 404 missing controller or action using a template and any other uncaught exceptions with a 500 server error which is also rendered out as a template.Here are those two templates:
not-found.phtml
server-error.phtmlThat's it. In case you are wondering where all of the HTML is in those templates, I use Zend_Layout so my action-based view scripts are quite minimal.
Now you have a top level catch-all that can handle routing errors without having to write a "No Route" plugin and you get a top level exception handler in case you let one slip by you. Which would never happen of course
Trackbacks
Trackback specific URI for this entry
No Trackbacks