Don’t rely on side effects in your code

Published on and tagged with cakephp  php  problem  software engineering

This post is inspired by a bug I encountered today. As I think it is an instructive bug, I will do a little code review of the relevant parts.

Ok, let’s dive into the code. First a bit of context:

// snippet from View::_render()
$loadedHelpers = $this->_loadHelpers($loadedHelpers, $this->helpers);

foreach(array_keys($loadedHelpers) as $helper) {

As we move to the View::_loadHelpers() function, we detect the following statement:

return $this->cakeError('missingHelperFile', array(array(
    'helper' => $helper,
    'file' => Inflector::underscore($helper) . '.php',
    'base' => $this->base

That is a bit weird, as the statement returns an error, but there was no error handling in the previous code snippet. But maybe the cakeError function just returns an empty array, who knows. So let’s have a look at the cakeError function defined in the Object class:

function cakeError($method, $messages) {
    if (class_exists('AppError')) {
        $error = new AppError($method, $messages);
    } else {
        $error = new ErrorHandler($method, $messages);
    return $error;

No, the function doesn’t return an array. Hm. As this function returns an object, and the first snippet expects an array, then there should be some PHP errors when displaying a “missing helper file” error. But there are no PHP errors. We find the answer in the ErrorHandler class: it just shows the error message and calls “exit” to stop the script execution. And so the returns are never called…

Well, this solution would work fine as long as it is only used internally (even though it is not very elegant). But the framework allows you to write a custom error handler, and so if you want to handle a “missing helper file” error yourself, you get PHP errors when you don’t use an exit.

That’s it. I hope you learned something from this example :)

© daniel hofstetter. Licensed under a Creative Commons License