Warning: preg_replace_callback(): Requires argument 2

Matei Zoc picture Matei Zoc · Jul 8, 2017 · Viewed 8.8k times · Source

I just updated PHP on my server from php 5 to php 7 and I'm getting these warnings:

Warning: preg_replace_callback() [function.preg-replace-callback0]: Requires argument 2, 'chr(\1)', to be a valid callback

Warning: preg_replace_callback() [function.preg-replace-callback0]: Requires argument 2, 'chr(0x\1)', to be a valid callback

Warning: preg_replace_callback() [function.preg-replace-callback0]: Requires argument 2, 'chr(\1)', to be a valid callback

Warning: preg_replace_callback() [function.preg-replace-callback0]: Requires argument 2, 'chr(0x\1)', to be a valid callback

This is the PHP code:

private function _decode( $source )
{
    $source = html_entity_decode($source, ENT_QUOTES, 'UTF-8');
    $source = preg_replace_callback('/&#(\d+);/me',"chr(\\1)", $source);
    $source = preg_replace_callback('/&#x([a-f0-9]+);/mei',"chr(0x\\1)", $source);

    return $source;
}

The Warning is come from:

$source = preg_replace_callback('/&#x([a-f0-9]+);/mei',"chr(0x\\1)", $source);

How i can fix this?

Answer

bishop picture bishop · Jul 8, 2017

The /e modifier (PREG_REPLACE_EVAL) is no longer supported, as noted in the PHP 7.0 migration guide. You need to use a callable function, not a string that will be evaluated as a function. In your case, replace your string function -- chr(0x\\1) -- with a Closure:

$source = preg_replace_callback(
    '/&#x([a-f0-9]+);/mi',
    fn($m) => chr(hexdec('0x'.$m[1])),
    $source
);

The inline string replacement of \\1 to yield a valid PHP hexadecimal, like 0x21, no longer works that way in the callable: you need a hexdec call to accomplish the same.

See it in action on 3v4l.org.


If you do not yet have PHP 7.4 with short closures, you need to write that as:

$source = preg_replace_callback(
    '/&#x([a-f0-9]+);/mi',
    function ($m) { return chr(hexdec('0x'.$m[1])); }, // Now a Closure
    $source
);