3

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?

Fred Gandt
  • 4,217
  • 2
  • 33
  • 41
Matei Zoc
  • 3,739
  • 3
  • 16
  • 18

1 Answers1

6

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
);
bishop
  • 37,830
  • 11
  • 104
  • 139
  • Working! but now i have the warning from $source = preg_replace_callback('/(\d+);/me',"chr(\\1)", $source); how i can fix this to? thank you – Matei Zoc Jul 07 '17 at 23:53
  • 1
    @MateiZoc In exactly the same way. Look at the code used and try to copy the functionality to your other method. You literally just need to copy the line, replace the regex and replace what `chr` returns. You don't even need to use hexdec as it's a decimal number. – h2ooooooo Jul 07 '17 at 23:56
  • @h2ooooooo i try $source = preg_replace_callback( '/(\d+);/me', function ($m) { return chr(hexdec($m[1])); }, // Now a Closure $source ); but im getting error Warning: preg_replace_callback() [function.preg-replace-callback0]: The /e modifier is no longer supported, use preg_replace_callback instead in Warning: preg_replace_callback() [function.preg-replace-callback0]: The /e modifier is no longer supported, use preg_replace_callback instead in – Matei Zoc Jul 07 '17 at 23:59
  • Remove the `e` in your regex, then change your callable to `return chr($m[1]);` – bishop Jul 08 '17 at 00:00