9

I am playing with try - catch block:

<?php
try {
    $str = "http://rejstrik-firem.kurzy.cz/73631604";
    $domOb = new DOMDocument();
    $html = $domOb->loadHTMLFile($str);
    $domOb->preserveWhiteSpace = false; 
    $container = $domOb->getElementById('ormaininfotab');   
    echo $container; // <========= this is intended error which I want catch
} 
catch (Exception $e) {
   echo "Exception" . $e->getMessage() . ". File: " . $e->getFile() . ", line: " . $e->getLine();
} 

catch (Error $e) {
   echo "Error" . $e->getMessage() . ". File: " . $e->getFile() . ", line: " . $e->getLine();
}
?>

My result is this:

Catchable fatal error: Object of class DOMElement could not be converted to string in /var/www/html/cirkve_ares/test.php on line 8

Why is not this error catched by second catch?

n4m31ess_c0d3r
  • 3,028
  • 5
  • 26
  • 35
Jarda K.
  • 161
  • 3
  • 10
  • OK, nobody interested in try-catch? In fact, for me is not this error problem. I am learning how exactly try-catch works in PHP. Can any body explain, how catching this types of errors? Why is not this error catched. – Jarda K. Jan 21 '17 at 11:07
  • just came across this same problem, also a E_RECOVERABLE_ERROR caused by being unable to convert to string.... – user2782001 May 26 '17 at 20:19

4 Answers4

4

As user2782001 mentioned this is not a bug in the eyes of PHP dev's. They even noted that these type of errors should be referenced as 'recoverable':

we should get rid of any references to "catchable" fatal errors (if they still exist) in favor of "recoverable" fatal errors. Using "catchable" here is confusing as they cannot be caught using catch blocks.

On the ErrorException manual page there is a neat workaround converting those "catchable/recoverable" errors to ErrorException.

<?php
function exception_error_handler($severity, $message, $file, $line) {
    if (!(error_reporting() & $severity)) {
        // This error code is not included in error_reporting
        return;
    }
    throw new ErrorException($message, 0, $severity, $file, $line);
}
set_error_handler("exception_error_handler");
?>

now you will be able to catch those errors with:

<?php
try {
    // Error code
} catch (Error $e) { // this will catch only Errors 
    echo $e->getMessage();
}
?>

or

try {
    // Error code
} catch (Throwable $t) { // this will catch both Errors and Exceptions
    echo $t->getMessage();
}
?>
  • IMO a disadvantage of the suggested error handler is that it changes the behavior of `error_reporting`. If someone comes along later and tries to change php.ini from `error_reporting = E_ERROR` to also include notices and warnings (in order to increase logging), all of a sudden notices and warnings will throw exceptions. So this handler has the effect of making notices, warnings, etc. effectively stop execution where before they just logged a message and continued. Maybe a better solution would be to not use error_reporting, but use a new config value or just wrap errors that stop execution. – xdhmoore Nov 18 '20 at 21:49
  • The above issue described [here](https://stackoverflow.com/questions/64815938/php-error-reporting-what-does-reporting-mean/64818070) – xdhmoore Nov 18 '20 at 21:55
  • @xdhmoore dont worry about the case you mention, just put an IF condition at the beginning of the "user error handler" to return false (so wont throw the ErrorException) when the error level (1st parameter of the error handler) are warnings and notices. – Esteban Jan 01 '22 at 05:11
  • @Esteban it's been a long time since I looked at this issue but wouldn't your suggestion require changing the error handler every time you want to change the logging levels, instead of being able to change them in the config file alone? – xdhmoore Jan 01 '22 at 19:23
  • @xdhmoore no, you just change the logging level in your php.ini (error_reporting), what I mean is that in your custom error_handler throw the ErrorException when the `$errno != warning and notices` (not saying `error_reporting() != warning and notices`). Finally I would say that throwing Exceptions inside the error_handler is a bad idea. – Esteban Jan 03 '22 at 05:36
2

Someone reported this as a bug to PHP's devs, who promptly decided it was not a bug. https://bugs.php.net/bug.php?id=72948&edit=3

This case has been intentionally omitted ...(in practice you can simply convert the recoverable fatal to an exception using an error handler...)

So you still have to use the

set_error_handler()

function, which we were all hoping to leave behind. PHP's devs are so good at never letting your day be too sunny...

Community
  • 1
  • 1
user2782001
  • 3,380
  • 3
  • 22
  • 41
1

There might be some fatal errors which are not even caught by set_error_handler() or \Throwable.

The below implementation will catch the errors which are not even caught by \Throwable as tested in php 7.1. It should only be implemented in your development environment(by just adding it in your development config file) and shouldn't be done in production.

Implementation

register_shutdown_function(function () {
    $err = error_get_last();
    if (! is_null($err)) {
        print 'Error#'.$err['message'].'<br>';
        print 'Line#'.$err['line'].'<br>';
        print 'File#'.$err['file'].'<br>';
    }
});

Example Error

Error# Class Path/To/MyService contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Path/To/MyServiceInterface::add)
Line# 12
File# Path/To/MyService.php
Kamal Soni
  • 1,522
  • 13
  • 15
0

It has been "fixed" as of PHP 7.4 according with Manual PHP, now it throws exception:

Existing recoverable fatal errors in string conversions have been converted to Error exceptions.

Esteban
  • 162
  • 8