Search code examples
phpregexpreg-replacepcrepreg-replace-callback

php converting preg_replace to preg_replace_callback


I'm working on this old code, and ran across this - which fails:

preg_replace('!s:(\d+):"(.*?)";!e', "'s:'.strlen('$2').':\"$2\";'", $sObject);

It tells me that preg_replace e modifier is deprecated, and to use preg_replace_callback instead.

From what I understand, I am supposed to replace the 's:'.strlen('$2').':\"$2\";' part with a callback function that does the replacement on the match.

What I DON'T quite get, is exactly what the regexp is doing that I'll be replacing. It's part of a bit to take php serialized data stuffed in a database field (dumb, I know ...) with broken length fields and fix them for reinsertion.

So can anybody explain what that bit is doing, or what I should replace it with?


Solution

  • Use

    preg_replace_callback('!s:(\d+):"(.*?)";!', function($m) {
          return 's:' . strlen($m[2]) . ':"' . $m[2] . '";';
    }, $sObject);
    

    The !e modifier must be removed. $2 backreferences must be replaced with $m[2] where $m is a match object containing match value and submatches and that is passed to the anonymous function inside preg_replace_callback.

    Here is a demo where the digits after s: get replaced with the $m[2] length:

    $sObject = 's:100:"word";';
    $res = preg_replace_callback('!s:(\d+):"(.*?)";!', function($m) {
          return 's:' . strlen($m[2]) . ':"' . $m[2] . '";';
    }, $sObject);
    echo $res; // => s:4:"word";