A Useful Error Controller Class For Zend Framework Applications
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.
class ErrorController extends Zend_Controller_Action
{
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');
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 controller "%s" in module "%s"',
$errors->request->getControllerName(),
$errors->request->getModuleName()
);
}
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;
case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION:
default:
// application error
$this->getResponse()->setHttpResponseCode(500);
$this->view->message = 'Application error';
$this->view->code = 500;
$this->view->info = $errors->exception;
break;
}
// send a mail to let someone know that there was a problem!
$config = Zend_Registry::get('configuration');
$tr = new Zend_Mail_Transport_Smtp($config->smtp);
Zend_Mail::setDefaultTransport($tr);
$mail = new Zend_Mail();
$emailBody = "An error occurred in the system. The error message contained the following output:\n\n";
$emailBody .= $this->view->message." (".$this->view->code.")\n\n";
$emailBody .= "Zend Error Type: ".$errors->type."\n\n";
$emailBody .= "REQUEST_URI: ".$_SERVER['REQUEST_URI']."\n\n";
if ( isset($_SERVER['HTTP_REFERER']) ) {
$emailBody .= "HTTP_REFERER: ".$_SERVER['HTTP_REFERER']."\n\n";
}
$emailBody .= "Stack trace: \n\n". $errors->exception->getTraceAsString()."\n\n";
// find the user to blame!
$username = Zend_Auth::getInstance()->getIdentity();
$emailBody .= "This error was created by ".$username.".";
$mail->setBodyText($emailBody);
$mail->setFrom('anAddress@example.com', '');
$mail->addTo($config->adminEmail, $config->adminName);
$mail->setSubject('An Error Occured');
// Email
$mail->send();
$this->view->title = 'Error!';
$this->view->heading = 'Error!';
// 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;
}
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.
smtp = my.smtpserver.com
adminEmail = admin@example.com
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.
$frontController = Zend_Controller_Front::getInstance();
$frontController->throwExceptions(false);
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'.
<h3>Error has happened. Inside this application. Sorry about that.</h3>
<p><?=$this->message ?> (<?=$this->code ?>) </p>
<?
if( $this->env == 'test' ) {
if ( isset($this->info ) ) { ?>
<? if ( 404 == $this->code ) { ?>
<p><b>Reason:</b> <?= $this->info ?></p>
<? } elseif (500 == $this->code) { ?>
<p>Bad server, naughty server!<br />No donut for you!</p>
<p><img src="<?=$this->baseUrl();?>/images/donut.jpg" /></p>
<h4>Exception information:</h4>
<p><b>Message:</b> <?= $this->info->getMessage() ?></p>
<h4>Stack trace:</h4>
<pre><?= $this->info->getTraceAsString() ?></pre>
<? } ?>
<? } ?>
<? } ?>
Really Useful Boxes sold here
suriplace
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.
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.
Keep working ,great job!
Congrats, a verry good and usefull class
Great ErrorController I just adopted it to my application (if you don’t mind) I will re-touch it later
I agree with 404 errors that O’Phinney told, but I also agree that is about which purposes you use it, in my case I need to know which 404 errors users faced up
This scenario is most for backend purposes for front end I totally agree with O’Phinney that you don’t need to know the 404 errors but again there are cases you may need it.
I will add some error logging I’m not yet sure if I will store the logs into database or into a file will check it later.
About line 49 before Stack Trace I added one line that will show me the exception message so it looks like this:
$emailBody .= “Exception Message: ” . $errors->exception->getMessage() . “\n\n”;
$emailBody .= “Stack trace: \n\n” . $errors->exception->getTraceAsString () . “\n\n”;
It’s so great. I love it!
I am new to the framework. I have been on one error for 2 days just to find out that this is the controller I needed. You have really helped me loads!! When I get better at it I promise to come back with additions to this.