Catching Warnings and Notices

Permanent Link: Catching Warnings and Notices 15. November 2008 RSS Feed for comments on RSS-Feed für Kommentare zu: Catching Warnings and Notices comments feed

Simple example: You want to open a file in PHP and there might be a slight possibility, that the file doesn't exist. Your code probably looks like this:

$fileHandle = fopen('text.txt', 'r');
if (!$fileHandle) {
print("Couldn't open file");
}

According to the php documentation, fopen will return FALSE if it can't open the file, but (and that's the annoying part), it will also generate a warning. Furthermore the php documentation suggests using @ before the function call to suppress the warning. Using @ before a function call is really, really bad coding and it makes your code slow (since @ changes the error_reporting to E_NONE before the function call and changes it back to what you had before after the function call) . But why return false, when it will generate a warning anyhow? Throwing an Exception would be the better way. Here's a way to do it.

First, we create a class containing a public static method that handles the error:

class ErrorHandler
{
    /**
    * catches php errors / warnings / notices and throws
    * an exception instead
    *
    * @param int $errNo
    * @param string $errStr
    */
    public static function handle($errNo, $errStr=NULL)
    {
        switch ($errNo) {
            case E_WARNING:
                throw new RuntimeException($errStr,$errNo);
            break;
            default:
                throw new Exception($errStr,$errNo);
            break;
        }
    }
}

The method handle has the error number and the error message, which are both generated by php. Error number would be something like E_NOTICE, E_WARNING or E_STRICT. The error string in this case would be "failed to open stream: No such file or directory' in /var/www/phpinfo.php:15".

Now we add a public static function method to the same class, that overwrites the php error handler with the method we just wrote:

/**
* Overwrites the PHP error handler and uses our own
*
*/
public static function set()
{
set_error_handler(array(__CLASS__ , 'handle'));
}

Now there's only one thing left to do: We have to call the set method at the beginning of our script:

ErrorHandler::set();

If we now execute the script again, we will not get a warning, instead we'll get an uncaught exception: Fatal error: Uncaught exception 'RuntimeException' with message 'fopen(text.txt) [function.fopen]: failed to open stream: No such file or directory' in /var/www/phpinfo.php:15 Stack trace: #0 [internal function]: ErrorHandler::handle(2, 'fopen(text.txt)…', '/var/www/phpinfo…', 35, Array) #1 /var/www/phpinfo.php(35): fopen('text.txt', 'r') #2 {main} thrown in /var/www/phpinfo.php on line 15

The cool thing is, that now we can simply catch the exception and will not flood the phperror log with Warnings, where they are probably not needed. Our script would now look like this:

ErrorHandler::set();
try {
    $fileHandle = fopen('text.txt', 'r');
} catch(Exception $e) {
    print("Couldn't open file");
}

Note, that you can catch anything but a fatal error.

14 comments

Loïc Hoguins Gravatar

Loïc Hoguin
13.12.2008, 10:52 o'clock

Hello, that's a good technique indeed.

Note however that your handler currently also throw exceptions when errors are silenced with the @ operator. In order to continue the script correctly when an error has been silenced, you need to add the following at the start of your handler: "if (error_reporting() == 0) return;". (see php.net/set_error_handler)

Even if it shouldn't happen often, sometimes you simply need to silence warnings and continue the script anyway.

Dominik Jungowski s Gravatar

Dominik Jungowski
13.12.2008, 14:14 o'clock

I can understand your point indeed,the question would be though: why suppress it with @ (and slowing things down),when i can just put the call in a try-catch-block ;)

Jagger Wangs Gravatar

Jagger Wang
13.12.2008, 16:38 o'clock

Good skill!

Loïc Hoguins Gravatar

Loïc Hoguin
13.12.2008, 21:33 o'clock

@Dominik

When working with third party code you cannot ensure that this code will avoid using @, and not filtering the silenced errors will thus break it. The errors needs to be silenced and no exception be thrown for the third party code to work correctly.

That's the most common example I've met, like when using PEAR with PHP5 and E_STRICT enabled.

You might also consider using the ErrorException class instead of the Exception class.

Dominik Jungowski s Gravatar

Dominik Jungowski
14.12.2008, 01:17 o'clock

Didn't think of that. In that case it surely makes sense

fuseros Gravatar

fusero
27.07.2009, 09:22 o'clock

i've seen that this method is quite popular in order to be able to manage PHP warnigns and notices… but i wonder (as a newbie in php eceptions) if there is a way to custom the exception to be thrown in the static method handle(). For example, i would like to be able to throw an IOException when a file cannot be open, or a MathException when i find a division by zero. Can i do this wothout having to search for key words in error message?

Dirk Pahls Gravatar

Dirk Pahl
17.06.2010, 15:25 o'clock

Hello,

found this post when looking for a method to deal with PHP notices and warnings and wondered about the sentence "Using @ before a function call is really, really bad coding and it makes your code slow.". So I wrote a little benchmark script:

$start = microtime(true);
for($i = 0; $i < 10000; $i++) {
@unserialize("unserializable");
}
$duration = microtime(true) - $start;
print("overall duration with @: $duration\n");

$start = microtime(true);
for($i = 0; $i < 10000; $i++) {
ErrorHandler::set();
try {
unserialize("unserializable");
}
catch(Exception $e) {}
ErrorHandler::reset();
}
$duration = microtime(true) - $start;
print("overall duration with error handler: $duration\n");

The function ErrorHandler::reset() is a call of restore_error_handler() as I want to go on with the initially configured error reporting settings after handling this notice.

The result of this little benchmark is completely different from what is said in the mentioned sentence above:

overall duration with @: 0.0735211372375
overall duration with error handler: 0.959964036942

Using the @ is more than ten times faster on my machine.

Dominik Jungowskis Gravatar

Dominik Jungowski
18.06.2010, 08:00 o'clock

Did the script without @ write an error message? If so, it should be the reason why it's so much slower.

Dirk Pahls Gravatar

Dirk Pahl
18.06.2010, 08:49 o'clock

No, it did'nt write an error message because I caught the exception … The two lines shown are the only output

Dominik Jungowskis Gravatar

Dominik Jungowski
18.06.2010, 10:31 o'clock

Then I would guess it's the try catch that makes it slow. It would be interesting to see what the script is like without the try-catch and without any output.

Dirk Pahls Gravatar

Dirk Pahl
18.06.2010, 10:42 o'clock

I removed throwing exceptions and catching them. After that the output is:

overall duration with @: 0.0508148670197
overall duration with error handler: 0.194847106934

First version is still 4 times faster. I think it's because setting and resetting the error handler in each loop. But even when I set end reset the error handler only one time before and after the loop I get:

overall duration with @: 0.051607131958
overall duration with error handler: 0.0809028148651

Both versions need nearly the same time now but using @ is still a bit faster.

Dominik Jungowskis Gravatar

Dominik Jungowski
18.06.2010, 11:24 o'clock

Which is strange, since @ modifies the error handling before and after each (function) call.

Are both benchmarks in one file or is it one file per benchmark?

Dirk Pahls Gravatar

Dirk Pahl
18.06.2010, 18:56 o'clock

Are both in the same file. When running in different files you get the same results. It seems to me that setting the error handler is even more expensive than what is done when using @.

Gecetauctioras Gravatar

Gecetauctiora
28.11.2011, 02:38 o'clock


Good Ol Boys Moving have gained a helpful popularity as an in a position packer in addition to moving company, on meeting both another country and local relocating digs up. Lots of people have previously put into use the requirements which is available from Good ol boys moving and found each of them worth his or her's claims. The company creates the option for with also policy in an effort to estimation ones moving about criteria ahead of time. The agency carries with it an comprehensive online circle for changers distribute via Nova scotia, simply put nearby progressing must have are became aquainted with at once. This agency has the benefit of incredibly professional solution around rapid point in time to ensure you really do not shed precious mobility effort during extraneous hold-up. Problems, attractive various other competitiveness, you must think about communicating with Good Ol Boys Moving.
good ol boys Moving stands out as the filling plus moving company to contemplate, you need to understand toward shorten any moving forward prerequisites. Good Ol Boys Moving makes certain that the necessary moving specifications are attained with stated wasted time you do not have to get anxious these days to the quality of the service distributed. Automobile called this manufacturer, make no mistake that your switching needs to have are increasingly cured from the greatest masters at the subject. You need to positively think about using the very 100 percent free quotations formula service of your organisation to actually estimation your personal changing prerequisites before you start. Aside from the great complimentary premiums system, there's also the power to obtain from the internet arranging on the move, so that you can chose the full workouts with travelling things to consider. All you have to accomplish is to always investigate freely available price quotes car loans calculator, review all your moving wishes as well as complete press announcements variety to learn from your products for good ol boys moving.

You will find many professional movers, when you're desiring to continue in one destination to one more, and you could discover that Good ol boys moving affords the very best system regardless of whether you're relocation locally as well as throughout the world. That good ol boys Moving has been doing this excellent brand cardio and it's definitely trustworthy as well as good. If you feel that Good Ol Boys Moving really are costly, then simply to your own astound, you will find that are particularly reasonably priced
That Good ol boys moving communicates the switch for everyone a simpler a single. It helps to have competent communicating while using the Good ol boys Moving office workers as it can show up the problem related to initiative connected with issues, that may add additional set you back inside your charges. A person have to be absolutely clear on their part regarding how what he or she have need to occur, as well moving company office workers will guarantee this not any kinda error in judgment is fully committed out of their component, may possibly give you discontent with the clientele. This unique Good ol boys moving organizations has been in the industry for decades and possess always been allowing terrific want to the nation's shoppers repeatedly.

Write a comment

(will not be published)