Search code examples
phperror-handlingerror-reportingerror-suppressione-notices

PHP notice suppression; only certain circumstances/methods


tl;dr - Is there an effective way to manage the error reporting level of PHP when working in a very strict environment, given certain processes would be made easier with a less strict level?

Alright; first off, I don't believe "error suppression" is a solution. I (am reasonably certain that I) have never used the @ error suppression operator, and have no intention of doing so. I take advantage of set_error_handler() and ErrorException (or some derivation of) and I develop in an error_reporting(-1) (future proof E_ALL | E_STRICT)

Now, I don't want to change these habits, as I find they are a great practice (also; if anyone has suggestions to further improve my development/production environment settings/practices, I'm all ears)

However, when it comes to view generation this can get slightly tedious. The correct data (array indices, variables, etc.) are not always available, given a controller fails to pass certain data to the view for whatever reason. As long as this data is non-critical to view generation, the view should still render.

I rather like this syntax as it's not verbose but (I think) highly understandable:

// e() is a shortcut function; given the passed value evaluates to a boolean true
// it will echo() and return true, otherwise it simply returns false
<p><?php e($data['field']) or e('No data found'); ?></p>

Of course, if $data['field'] isn't invoking offsetGet() with null returned in absence of the index, we have a problem. Notice meet exception, exception meet script failure.

I've experimented with different implementations, including creating a data tree using a node-like class to manage lists/rows of data passed to the view. __get() would actually create nodes (on assignment or access) that don't exist (as to simplify node data assignment, and to prevent issuing notices. __isset() tested for validity and would return false appropriately though) It also implemented ArrayAccess for accessing the node data, and would simply return null on a missing index.

I've opted to abandon this implementation due to the overhead of PHP's magic (though I learned alot about refactoring/optimization and profiling)

I've gone with native arrays instead, but now the codebase for my views is littered with isset(), and frankly that's just irritating (nearly more than the performance loss of the aforementioned implementation)

Now, I was thinking the easiest fix would be to slide the error_reporting() notch up and down based on where we are in the script:

// View::render()
public function render($data){
    error_reporting(E_ALL & ~E_NOTICE);
    // view generation logic
    error_reporting(-1);
}

But that doesn't seem like the cleanest (nor safest) fix; especially when helper functions are called within a view. I've gone for a sort of HMVC approach, and sub-requests can be issued from a view, so I'd need to find all the render() escape points and guard them with error_reporting(-1).

Do I have any other options?


Solution

  • "undefined variable" notices are very valuable, even in view templates, as they help to spot typos; but this requires to either define every variable in the controllers, or to check if they are set in views.

    As you noticed, the two obvious solutions have some overhead or drawbacks. Even disabling error reporting has some overhead since errors are still generated (the error message is formatted, internal and user error handlers are called, etc; they are just hidden). And this hides errors from helper methods you may call from the views; this doesn't helps debugging.

    I would recommand you to go with a template engine. Some generate PHP code as fast as hand-written code. They will handle this for you, and will do more (like escaping, your views should also be littered with htmlspecialchars() calls ;) ).