Search code examples
phpwordpresspreg-replacephp-7preg-replace-callback

Does anyone know why this isn't working? Working on: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instea


When we switched to php7 suddenly a particular Wordpress plugin started to trough this error:

preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead.

So i've started to search (i'm not a php expert) and came with this rewriting of the call.

Something is definitely wrong (although the error disappeared) because the plugin does not do the job. Any clue somebody? Thank you

//old
//$rewrite_rules = unserialize( preg_replace         ( '!s:(\d+):"(.*?)";!se',                        "'s:'.strlen('$2').':\"$2\";'"         , $rewrite_rules ) );
//new
  $rewrite_rules = unserialize( preg_replace_callback( '!s:(\d+):"(.*?)";!s',  function($m) { return ("'s:'.strlen('$m[2]').':\"$m[2]\";'");}, $rewrite_rules ) );

Solution

  • There are several issues with your callback:

    function($m) { return ("'s:'.strlen('$m[2]').':\"$m[2]\";'");}
    

    The biggest one is that it returns the string:

    "'s:'.strlen('$m[2]').':\"$m[2]\";'"
    

    Being a string enclosed in double quotes, the variables are substituted with their values but that's all. Apparently you need to also find the length of $m[2] and the function strlen() is the right tool for this job. But here strlen are just some characters in a string, not a function call. In order properly call strlen() to get the length of $m[2] it should be invoked as PHP code, outside the string, like this:

    's:'.strlen($m[2]).':"'.$m[2].'";'
    

    Even better, use sprintf() to produce the output in a clean way, without worrying about quotes and escaping quotes inside quotes and so on:

    function (array $m) {
        return sprintf('s:%d:"%s";', strlen($m[2]), $m[2]);
    }