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:
set_error_handler
seems like overkill because I have to use it to filter every warning in the page (is this true?);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?
The solution that really works turned out to be setting simple error handler with
E_WARNING
parameter, like so:You should probably try to get rid of the warning completely, but if that's not possible, you can prepend the call with @ (i.e. @dns_get_record(...)) and then use any information you can get to figure out if the warning happened or not.
I wanted to try/catch a warning, but at the same time keep the usual warning/error logging (e.g. in
/var/log/apache2/error.log
); for which the handler has to returnfalse
. However, since the "throw new..." statement basically interrupts the execution, one then has to do the "wrap in function" trick, also discussed in:Is there a static way to throw exception in php
Or, in brief:
EDIT: after closer inspection, it turns out it doesn't work: the "
return false && throwErrorException ...
" will, basically, not throw the exception, and just log in the error log; removing the "false &&
" part, as in "return throwErrorException ...
", will make the exception throwing work, but will then not log in the error_log... I'd still keep this posted, though, as I haven't seen this behavior documented elsewhere.I would only recommend using @ to suppress warnings when it's a straight forward operation (e.g. $prop = @($high/($width - $depth)); to skip division by zero warnings). However in most cases it's better to handle.
Be careful with the
@
operator - while it suppresses warnings it also suppresses fatal errors. I spent a lot of time debugging a problem in a system where someone had written@mysql_query( '...' )
and the problem was that mysql support was not loaded into PHP and it threw a silent fatal error. It will be safe for those things that are part of the PHP core but please use it with care.No further output - good luck debugging this!
This time we can see why it failed.
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()
.You could build on this idea and write a re-usable error handler that logs the errors for you.
Turning errors into exceptions
You can use
set_error_handler()
and theErrorException
class to turn all php errors into exceptions.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 onset_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.