Search code examples
phperror-handlingtry-catch

Can I try/catch a warning?


I need to catch some warnings being thrown from some php native functions and then handle them.

Specifically:

array dns_get_record  ( string $hostname  [, int $type= DNS_ANY  [, array &$authns  [, array &$addtl  ]]] )

It throws a warning when the DNS query fails.

try/catch doesn't work because a warning is not an exception.

I now have 2 options:

  1. set_error_handler seems like overkill because I have to use it to filter every warning in the page (is this true?);

  2. Adjust error reporting/display so these warnings don't get echoed to screen, then check the return value; if it's false, no records is found for hostname.

What's the best practice here?


Solution

  • Set and restore error handler

    One possibility is to set your own error handler before the call and restore the previous error handler later with restore_error_handler().

    set_error_handler(function() { /* ignore errors */ });
    dns_get_record();
    restore_error_handler();
    

    You could build on this idea and write a re-usable error handler that logs the errors for you.

    set_error_handler([$logger, 'onSilencedError']);
    dns_get_record();
    restore_error_handler();
    

    Turning errors into exceptions

    You can use set_error_handler() and the ErrorException class to turn all php errors into exceptions.

    set_error_handler(function($errno, $errstr, $errfile, $errline) {
        // error was suppressed with the @-operator
        if (0 === error_reporting()) {
            return false;
        }
        
        throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
    });
    
    try {
        dns_get_record();
    } catch (ErrorException $e) {
        // ...
    }
    

    The important thing to note when using your own error handler is that it will bypass the error_reporting setting and pass all errors (notices, warnings, etc.) to your error handler. You can set a second argument on set_error_handler() to define which error types you want to receive, or access the current setting using ... = error_reporting() inside the error handler.

    Suppressing the warning

    Another possibility is to suppress the call with the @ operator and check the return value of dns_get_record() afterwards. But I'd advise against this as errors/warnings are triggered to be handled, not to be suppressed.