debuggable

 
Contact Us
 

Dessert #9 - Graceful Error Handling

Posted on 17/9/06 by Felix Geisendörfer

Deprecated post

The authors of this post have marked it as deprecated. This means the information displayed is most likely outdated, inaccurate, boring or a combination of all three.

Policy: We never delete deprecated posts, but they are not listed in our categories or show up in the search anymore.

Comments: You can continue to leave comments on this post, but please consult Google or our search first if you want to get an answer ; ).

By default CakePHP is very nice to us by showing useful Controller/Model/Component/View/etc.-Missing errors whenever we forgot or were too lazy to create them. However, as soon as you start to write an application and modify your AppController, you'll eventually notice that the Controller invoking proccess is (and has to) be done a little bit different in case of an error compared to a normal Controller action call. Most notably in this scenario is that Controller::constructClasses() does not get executed which causes big problems if you try to access Models in your AppController's beforeFilter or one of your components startup() functions. This in turn will produce a big mess in your views if you pull something like a Navigation out of the database, because now you might get fatal php errors, or the view variable will be empty and if you didn't put checks for that in the view it will produce tons of php warnings. In this dessert I'm going to show you a couple ways of detecting and handling those situations.

Ways to detect error situations

One of the most obvious ones is to check whether the Model you want to access exists or not and then make the decision based on that, for example like this:

function beforeFilter()
{
    if (!isset($this->Menu))
        // Do something
}

Another thing I noticed when experimenting with this was that some of the usual Controller properties do not or get set later when an error pop's up. So you can use this to detect an error situation like this:

function beforeFilter()
{
    if (empty($this->action))
        // Do something
}

Or another, pretty logical, approach is to simply check if the ErrorHandler class has been included which is responsible for handling the error:

function beforeFilter()
{
    if (class_exists('ErrorHandler'))
        // Do something
}

Now most of the times I would suggest you to use method #1 of checking whether the object you want to interact with exists, but maybe sometimes you want your application to behave different in case of an error without having to depend on loaded Models, that's when I would recommend you method #3 or method #2 (in case method #3 is problematic because of your application's setup).

Handling the error

Now there are different ways to handle this error as well. In case the reference to your Menu Model is missing, but you want to make sure your Menu get's populated anyway, this is way #1 to do it:

function beforeFilter()
{
    if (!isset($this->Menu))
        $this->Menu =& new Menu();
}

or if you believe that the problem didn't arise due to a Model Missing error of some Model for sure, you can also execute the Controller::constructClasses() function by yourself:

function beforeFilter()
{
    if (!isset($this->Menu))
        $this->constructClasses();
}

For my applications I mostly use method #2 because I don't expect Model missing errors to pop up too much. The advantage of using it is that you don't have to invoke the Models yourself which can eventually cause some issues if the Model::__construct() parameters are required for your model to work correctly. But other then that there isn't anything wrong with using method #1 either.

Conclusion

If you have any questions concerning which method's to use feel free to ask. This situation has been one of my most frustrating problem with CakePHP in the past, but after discovering the method's above I was able to deal with it pretty so far. Let me know what your take on this is.

--Felix Geisendörfer aka the_undefined

 
&nsbp;

You can skip to the end and add a comment.

This post is too old. We do not allow comments here anymore in order to fight spam. If you have real feedback or questions for the post, please contact us.