I need to catch some warnings thrown from PHP native functions and process them.
Especially:
array dns_get_record ( string $hostname [, int $type= DNS_ANY [, array &$authns [, array &$addtl ]]] )
When a DNS query fails, it will raise a warning.
try / catch does not work because warnings are no exception.
I now have two choices:
Set_error_handler seems to have some set_error_handler because I have to use it to filter every warning on the page (is this true?);
Adjust the error report/display so that these warnings do not appear on the screen, then check the return value; if false, no record of the host name can be found.
What are the best practices here?
#1st floor
A really effective solution is to set up a simple error handler using the E_WARNING parameter, as follows:
set_error_handler("warning_handler", E_WARNING); dns_get_record(...) restore_error_handler(); function warning_handler($errno, $errstr) { // do something }
#2nd floor
You should probably try to completely eliminate the warning, but if that's not possible, you can add @ (i.e. @dns_get_record(...) before the call, and then use any information you can get to determine if the warning occurred or not.
#3rd floor
Setting and Restoring Error Handlers
One possibility is to set up your own error handler before invoking it and later use restore_error_handler() to restore the previous error handler.
set_error_handler(function() { /* ignore errors */ }); dns_get_record(); restore_error_handler();
You can build on this idea and write reusable error handlers to record errors for you.
set_error_handler([$logger, 'onSilencedError']); dns_get_record(); restore_error_handler();
Turn errors into exceptions
You can use the set_error_handler() and ErrorException classes to convert all php errors to exceptions.
set_error_handler(function($errno, $errstr, $errfile, $errline, $errcontext) { // 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) { // ... }
An important thing to note when using your own error handler is that it will bypass the error_reporting setting and pass all errors (notifications, warnings, etc.) to your error handler.You can set a second parameter on set_error_handler() to define the type of error you want to receive, or you can access the current setting using... = error_reporting() in the error handler.
Prohibit Warning
Another possibility is to disable the call using the @ operator and then check the return value of dns_get_record().However, I recommend not to do this because errors/warnings are triggered rather than suppressed.
#4th floor
If dns_get_record() fails, it returns FALSE, so you can use @ to suppress the warning and check the return value.
#5th floor
I want to try/capture warnings, but keep the usual warning/error log records (for example, at/var/log/apache2/error.log); the handler must return false for this.However, since the "throw new..." statement essentially interrupts execution, the "wrap in function" technique, which is also discussed below, must be executed:
Is there a static method that raises an exception in php
Or, in short:
function throwErrorException($errstr = null,$code = null, $errno = null, $errfile = null, $errline = null) { throw new ErrorException($errstr, 0, $errno, $errfile, $errline); } function warning_handler($errno, $errstr, $errfile, $errline, array $errcontext) { return false && throwErrorException($errstr, 0, $errno, $errfile, $errline); # error_log("AAA"); # will never run after throw /* Do execute PHP internal error handler */ # return false; # will never run after throw } ... set_error_handler('warning_handler', E_WARNING); ... try { mkdir($path, 0777, true); } catch (Exception $e) { echo $e->getMessage(); // ... }
Edit: On close inspection, it is found that it does not work: "return false & & throwErrorException..." will basically not throw an exception, but will simply log in to the error log; deleting the "false &&" section (such as the section in "return throwErrorException...") will cause the exception throw to work correctly, but will not log in error_log afterwards...but I'll keep this message because I haven't done so yet and haven't seen this behavior documented elsewhere.