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.