Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deprecation warning not catchable in PHP 7.4

Tags:

php

php-7.4

In PHP 7.4.0 I see the following warning:
Deprecated: Array and string offset access syntax with curly braces is deprecated in ...
My error / exception handlers are not able to catch and log them.

Example:

<?php
    set_error_handler(function ($errNo, $errStr) {
        echo "set_error_handler: " . $errStr;
    });

    set_exception_handler(function ($exception) {
        echo "set_exception_handler: " . $exception->getMessage();
    });

    $b = 'test';
    $a = $b{1};

The warning is still displayed in the normal output and none of the two handlers is called.

I want to log all errors, exceptions and warnings in my own log but this warning is not being catched by the handlers. Is there a reason for this or a solution to catch and log everything PHP is complaining about (have no access to the servers Apache/PHP log)?

like image 346
Dave Avatar asked Jan 06 '20 21:01

Dave


1 Answers

set_error_handler catches messages emitted at run-time, per the docs:

This function can be used for defining your own way of handling errors during runtime

The deprecation warning you're seeing is implemented at compile-time, which by definition occurs before run-time:

static zend_op *zend_delayed_compile_dim(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
{
    if (ast->attr == ZEND_DIM_ALTERNATIVE_SYNTAX) {
        zend_error(E_DEPRECATED, "Array and string offset access syntax with curly braces is deprecated");
    }
    ...

You might think of it as a "soft syntax error": it's discovered while parsing, during the compilation step, but rather than being a hard fatal, it's a warning of future doom. Like syntax errors, you have two ways of handling them: prepending and shutdown handling.

Prepending

$ cat error-handler.php
<?php
set_error_handler(fn(...$args) => var_dump($args));
$ cat try.php
<?php
$b = 'test';
$a = $b{1};
$ php -d auto_prepend_file=error-handler.php try.php
array(5) {
  [0]=>
  int(8192)
  [1]=>
  string(69) "Array and string offset access syntax with curly braces is deprecated"
  [2]=>
  string(21) "/Users/bishop/try.php"
  [3]=>
  int(3)
  [4]=>
  NULL
}

Shutdown handling

register_shutdown_function(fn() => var_dump(error_get_last()));

$b = 'test';
$a = $b{1};

Outputs:

array(4) {
  ["type"]=>
  int(8192)
  ["message"]=>
  string(69) "Array and string offset access syntax with curly braces is deprecated"
  ["file"]=>
  string(9) "/in/212CF"
  ["line"]=>
  int(7)
}

Which to use?

Choose either or both, depending upon your needs. Personally, I use the prepend approach, as it handles various other White Screen of Death scenarios. If you're doing this in web context, you'll need to arrange your web server to set the auto_prepend_file setting: once your "main" code's running, you can't set prepend and have it work as demonstrated here.

like image 158
bishop Avatar answered Oct 01 '22 17:10

bishop