Handling errors in Zend Framework

March 2, 2009 – 6:20 pm Tags: ,

In Zend Framework based applications, error handling is typically done using the error controller, but there are different ways to send the execution to it – some better than others.

Let’s look at some ways to trigger the error controller and how to have it handle different error conditions.

Error controller structure

Let’s quickly cover the basics of the error controller first:

  • To enable the error controller, you need to set throwExceptions to false in the front controller:
    $fc->throwExceptions(false);
  • The Zend Framework Reference Guide has a chapter on the Error Controller where you can learn the basics

Now, how to structure your error controller?

The easiest way out is, of course, to just handle everything in the errorAction method. However, it will be easier to understand the controller, if you separate different error types into separate actions. This also allows us to easily have error-specific code without bloating the errorAction method too much, in addition to allowing us to easily render error-specific view scripts.

class ErrorController extends Zend_Controller_Action {
  public function errorAction() {
    $error = $this->_getParam('error_handler');
    switch(get_class($error->exception)) {
      case 'PageNotFoundException':
        $this->_forward('page-not-found');
        break;
 
      case 'NotAuthorizedException':
        $this->_forward('not-authorized');
        break;
 
      default:
        //put some default handling logic here
        break;
    }
  }
 
  public function pageNotFoundAction() {
    //goes here if the page was not found
  }
 
  public function notAuthorizedAction() {
    //goes here if the user has no access to a page
  }
}

So in the above example, the errorAction would be used to determine the type of the error, and then the request would be forwarded to the respective action. Errors that don’t have a specific action for them can have some generic handling in errorAction.

Triggering the error controller

The most common approach to trigger the error controller is to simply forward the request to it in an erroneous condition:

class SomeController extends Zend_Controller_Action {
  public function someAction() {
    if($this->_getParam('foo',false)) {
      //parameter present - ok
    }
    else {
      //parameter not present - error
      $this->_forward('some-error', 'error');
    }
  }
}

While simple, this approach has a small flaw: The forwarding code is essentially creating a coupling between this controller and the error controller!

If you want to make your code easily re-usable, this is a no-no. By forwarding to a specific action, you are requiring anyone who wants to use the code to implement an error controller with the actions your code requires.

A better approach would be to use exceptions. Instead of forwarding, you throw an exception:

class SomeController extends Zend_Controller_Action {
  public function someAction() {
    if($this->_getParam('foo',false)) {
      //parameter present - ok
    }
    else {
      //parameter not present - error
      throw new ParameterNotFoundException('oh no!');
    }
  }
}

This time we are throwing a custom exception called ParameterNotFoundException. By doing this, we allow the normal error handling code of the framework to take over: the error is caught, and the request is forwarded to the error controller.

Now you can add some code in the error controller to handle this kind of exceptions. Or maybe your project does not need custom handling for this exception, so you can simply use the generic handling code for it.

In closing

There’s not much to error handling in ZF thanks to the ready components that make it really easy. Just throw an exception, and write some code in the error controller to handle it. As a rule of thumb, you should at least log the exceptions that get as far as the error controller!

Further reading:
There are lots of other posts about Zend Framework in this blog

Share this:
  1. 50 Responses to “Handling errors in Zend Framework”

  2. just testing the speed of this post

    By elmo on Mar 3, 2009

  3. Great post as usual :)

    By Federico on Mar 3, 2009

  4. Great post. I shall update my post on CSRF protection to mention your post and using exceptions rather than the _forward method.

    By Tom Graham on Mar 3, 2009

  5. Good writing!

    Though, how do you get to use the ErrorController::notAuthorizedAction()?

    By Iulian on Mar 4, 2009

  6. You can use the exception property of the error handler to see what type of exception was thrown. Then you just do $this->_forward(‘notAuthorizedAction’), if the exception is of the type for that.

    By Jani Hartikainen on Mar 4, 2009

  7. Updated the code example to show comparing the exception type and forwarding to the appropriate action

    By Jani Hartikainen on Mar 4, 2009

  8. Great one dude! You’ve just win a place in my RSS ;).

    By Pacek on Mar 4, 2009

  9. Where would you declare the exception class ?
    In the same file as the SomeController class, in a separate file ?

    By Yann on Mar 5, 2009

  10. As per usual PHP conventions, one class per file.

    By Jani Hartikainen on Mar 5, 2009

  11. Awesome! A really genious ErrorHandling. What kinds of Exception could be exist?

    ParameterNotFoundException who knows some more?
    PageNotFoundException?

    By Stormbind on Mar 6, 2009

  12. What about handling errors that do not come from controllers but Authentication Plugin::preDispatch() that extends Zend_Controller_Plugin_Abstract. In this way I get kicked out from dispatch loop with this exception:
    “Test_Exception: NOT_AUTHORIZED in library\Test\Controller\Plugin\Auth.php on line 32
    1 {main}( ) ..\index.php:0
    2 Zend_Controller_Front->dispatch( ) ..\index.php:42″

    how to walk around it?

    By kido on Mar 8, 2009

  13. kido, as far as I know, any exceptions thrown in controller plugins, or action helpers or any other, should be caught by the front controller.

    This is assuming you have throwExceptions set to false as mentioned in the post.

    By Jani Hartikainen on Mar 8, 2009

  14. Nice post Jani ;)
    Again, very clear and thoughtful.
    I wrote my own ErrorController too, this is very powerful to control every errors thrown to the user face when the application is not used by a dev :D

    Regards,

    Naunaud.

    By Naunaud on Mar 8, 2009

  15. Hi Jani
    The error was my fault because I mistyped in a list of allowed controllers. I was throwing this exception twice. One exiting loop was thrown in preDispatching of error controller.

    But my problem is: when I’m throwing “NotAuthorizedException” from preDispatch plugin the exception is registered but an action is still executed (probably coz ErrorHendler is a postDispatch).

    I think that throwing exception(and dealing with them in proper controller) would be better than redirecting, but I can’t do it simple way.

    Cheers, and many thnx

    By kido on Mar 8, 2009

  16. I’ve got a strange issue coming up with this solution. The following will throw an exception saying the action cannot be found:

    $this->_forward(‘pageNotFound’);
    public function pageNotFoundAction() {}

    However, if I remove camelcasing, it works:

    $this->_forward(‘pagenotfound’);
    public function pagenotfoundAction() {}

    By Kimmo on May 1, 2009

  17. Yeah that’s my mistake.. actually you should not use camelcasing when forwarding – use dashes.

    for example:
    public function camelCasedAction()

    $this->_forward(‘camel-cased’)

    I’ve updated the examples to show the correct way to do forwarding.

    By Jani Hartikainen on May 1, 2009

  18. Is it possible to create a global exception handler, that will work without manually throwing exceptions in the controller?

    By Snowcore on May 6, 2009

  19. How do you create a custom exception such as ParameterNotFoundException?

    class ParameterNotFoundException extends Zend_Controller_Exception
    {}

    or something like that. I’m trying to generate a exception when I test for:

    if(!$acl->isAllowed($roleName,$resourceName,$privilageName)){
    throw new Zend_Controller_Action_Exception(‘Testing action exception’, 404);
    $request->setModuleName(‘default’)
    ->setControllerName(‘Error’)
    ->setActionName(‘error’);
    }

    but instead of going to the error controller I get a message: Uncaught exception ‘Zend_Controller_Action_Exception’

    so if you could point me in the right direction into creating my own custom exception classes I’ll appreciate it very much!

    By Fabian on May 7, 2009

  20. Snowcore: The error controller will work even if you don’t throw exceptions yourself. Any exceptions thrown by any code will be caught by the front controller (if you have throwExceptions set to false) and forwarded to the error controller.

    You could also use set_exception_handler.

    Fabian: you must actually throw your custom exception. The code you show is throwing a Zend_Controller_Action_Exception.

    By Jani Hartikainen on May 7, 2009

  21. So how do I go about creating the new custom exception class? So I can stap throwing my own custom exceptions.

    Thanks,
    Fabian

    By Fabian on May 8, 2009

  22. Ah sorry, misunderstood your problem. Yes, the code you showed for creating the exception should work, but you may want to inherit from just Exception.

    By Jani Hartikainen on May 8, 2009

  23. Sorry to keep bugging you like this , but I created the custom execption at:
    Library/Zend/authorizeException.php

    class Zend_AuthorizeException extends Exception
    {}

    so when I do this:
    throw new Zend_AuthorizeException(‘Testing exception’, 404);

    I get a fatal error: Uncaught exception ‘Zend_AuthorizeException’.

    It’s like it never entered the error_handling plugin.

    I checked that the throwExceptions = false; and Also added this to my bootstrap just to make sure.

    $frontController->throwExceptions(false);

    By Fabian on May 8, 2009

  24. Hi,

    What about errors/exceptions the application may encounter BEFORE the front controller dispatches? For example, database connection is done prior to front controller dispatch, but what if, when attempting to connect to database you get an exception? How would you route to the error controller?

    By stefan on May 11, 2009

  25. Some use a controller plugin to initialize their DBs etc., which would solve this. The alternative to that is putting your DB connection code in a try-catch block.

    By Jani Hartikainen on May 12, 2009

  26. Thanks for your answer,

    I knew about the controller plugin solution to this problem but I always go with a bootstrap class in my zend framework powered applications. I also found this http://www.nabble.com/Process-to-an-ErrorController-when-an-exception-has-been-catched-td19607161.html which I even tried at some point but with no success.

    By stefan on May 12, 2009

  27. Just a small question:
    Where would you put the custom Exception classes in your directory structure? If I throw an exception, it is going to look for an exception, would anybody know where and how to handle this?

    By Yorian on Nov 9, 2009

  28. You would put the class to the library directory, for example library/Foobar/Exception.php

    By Jani Hartikainen on Nov 9, 2009

  29. Sounds a bit like a “dirty” solution (just because this is the include path). Would it be possible to use the auto loader zend uses automatically?

    By Yorian on Nov 9, 2009

  30. You typically put “infrastructure” code such as custom exceptions in the library dir. It will work just fine with ZF autoloader, assuming you name your class correctly and you’ve configured the autoloader right.

    By Jani Hartikainen on Nov 9, 2009

  31. Somehow it doesn’t seem to work with me, just some information:

    My directory structure:
    /application
    /modules
    /default
    /Exception
    /Exception/UserNotFound.php

    In a certain model (also in the default module) I throw the exception like this:

    throw new Exception_UserNotFound(‘User could not be found’);

    In UserNotFound.php I have the following:
    class Exception_UserNotFound extends Zend_Exception {}

    By Yorian on Nov 9, 2009

  32. BTW, I get the following error:

    Fatal error: Class ‘Exception_UserNotFound’ not found in C:\xampp\server\application\modules\default\controllers\UserController.php on line 22

    By Yorian on Nov 9, 2009

  33. Yes there are different ways to send the execution to it and some better than public works handling is typically.

    By public works energy on Apr 19, 2010

  34. that default error is not good how can i show my error message by detail my error message always show Application error so i can’t know where is my error and which error is occured

    By batmagnai on Jul 8, 2010

  35. why this error controller is not accessing by simply typing as url
    application/admin/error
    although this controller exist…
    :(
    it shows error
    Fatal error: Uncaught exception ‘Zend_Controller_Dispatcher_Exception’ with message ‘Invalid controller class (“Admin_ErrorController”)’ in C:\xampp\htdocs\asiandirectors\library\Zend\Controller\Dispatcher\Standard.php……..
    plz help me out …its urgent :(

    By richa on Jul 12, 2010

  36. richa, I’d suggest seeking help on the #zftalk irc channel on irc.freenode.net

    By Jani Hartikainen on Jul 15, 2010

  37. Hi

    How do I stop ZF from rendering the output in the Action that the Exception is thrown?

    I have a an action which may throw an Exception, the Exception is handled in my ErrorController. The problem is that the output from the orignal Exception is shown along with any output from the ErrorController.

    Is this expected or have I done something wrong?

    By Jake Noble on Aug 21, 2010

  38. Jake, when an exception happens in one of your controllers, it should go to the error controller without any output from the current controller. So yeah, sounds like there could be a problem in your code. Explicitly rendering or echoing stuff, perhaps?

    By Jani Hartikainen on Aug 22, 2010

  39. Jani, thanks for the response. The Exception is not being thrown in a controller, but in a plug in. The plug in loads and checks my Acl. I then throw an Exception if something is wrong.

    If I throw the same Exception from within a controller it works fine. Any ideas on how to do this from within my plug in?

    By Jake Noble on Aug 23, 2010

  40. It seems others have this issue too, but I have yet to find a solution so I asked about it on Stack Overflow, in case your interested … http://stackoverflow.com/questions/3548282/handling-exceptions-thrown-in-zend-frameworks-controller-plugins

    By Jake Noble on Aug 23, 2010

  41. I posted an answer (or at least an idea) to the SO question :)

    By Jani Hartikainen on Aug 24, 2010

  42. I have a an action which may throw an Exception, the Exception is handled in my ErrorController. The problem is that the output from the orignal Exception is shown along with any output from the ErrorController.

    By Arkadaşlık sitesi on Aug 24, 2010

  43. Folks, kind of related to this, if you’re using Action Helpers w/ hooks to autorun, read my issue on Stack Overflow:

    http://stackoverflow.com/questions/4076578/do-action-helpers-with-hooks-to-auto-run-throw-exceptions-or-not/4082325

    You want to make sure to trap exceptions.

    By Joe Devon on Nov 3, 2010

  44. güzel bi paylaşım olmuş.
    yazanlara teşekkürler

    By blackberry servisi on Jan 12, 2011

  45. I am having a problem when typing as url app, there apparently is the controller, but it displays an error flag for some reason

    By Simon on Feb 11, 2011

  46. Hi i am kavin, its my first occasion to commenting anywhere, when i read this paragraph i thought i could
    also create comment due to this sensible paragraph.

    By melia biyang spray on Sep 21, 2014

  47. Hello, I think your site might be having browser compatibility issues.
    When I look at your blog site in Firefox, it looks fine but when opening in Internet Explorer, it has some overlapping.
    I just wanted to give you a quick heads up! Other then that, fantastic blog!

    By nufamco.net on Sep 22, 2014

  1. 4 Trackback(s)

  2. Mar 3, 2009: links for 2009-03-03 « sySolution
  3. Mar 8, 2009: 網站製作學習誌 » [Web] 連結分享
  4. Apr 28, 2009: Zend Framework Starter | www.pokeroconnor.com
  5. Nov 9, 2009: Custom Exceptions - Zend Framework Forum

Post a Comment

You can use some HTML (a, em, strong, etc.). If you want to post code, use <pre lang="PHP">code here</pre> (you can replace PHP with the language you are posting)