Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Symfony 1.4 using deprecated functions in php 5.5

I recently upgraded PHP from version 5.3.27 to 5.5.0. Everything is working fine in my Symfony 2.3.2 project, and I can enjoy the latest PHP functionalities.

Now when I am going back to my other Symfony 1.4.16 project, I get a PHP error about preg_replace being deprecated with the /e modifier.

I can find no reference about this error in the forums: Has anyone had this problem before ? Is there any kind of patch that I could apply out of the box ? Is an upgrade to Symfony 1.4.20 going to fix this issue ?

The error message goes like this:

Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in /myproject/lib/vendor/symfony/lib/response/sfWebResponse.class.php on line 409

One way to go may be to modify the code as recommended in the message, and in the manual. How can I change my preg_replace expression to a preg_replace_callback call ?

Any help / hint will be very welcome.

EDIT:

To this date, there is no patch for this (and Symfony 1.4.20 does not address the issue). The solution is to replace failing calls to preg_replace with corresponding call to preg_replace_callback in the sourche, which is easily done in the sfWebResponse class (thanks for the hint Jon). Now next failing occurrence is slightly more complex, unfortunately... And on the other hand, we probably would have to grep for preg_replace uses with /e option in order to find out where Symfony is likely to break. Which gives quite a few results :o

So... My conclusion would be that Symfony 1.4 users would better not upgrade PHP to version 5.5 until some serious patch comes out. What do you think ? Any alternative ?

like image 747
mika Avatar asked Aug 06 '13 10:08

mika


3 Answers

The errors do not show up in prod unless you have enabled debug in index.php. It' s also possible to remove them in dev by unsetting the E_DEPRECATED flag in settings.yml :

dev:
  .settings:
    error_reporting:  <?php echo ((E_ALL | E_STRICT) ^ E_DEPRECATED)."\n" ?>
like image 104
flm Avatar answered Oct 06 '22 15:10

flm


Basically what you have to do is take the replacement argument from the preg_replace call and factor it out into a proper PHP expression, then make that expression the body of a function that will be used as the callback to the equivalent preg_replace_callback call.

In your case the relevant code is

return preg_replace('/\-(.)/e', "'-'.strtoupper('\\1')", /* input */)

So you would do that as

$callback = function($matches) {
    return '-'.strtoupper($matches[1]);
};

return preg_replace_callback('/\-(.)/', $callback, /* input */)

As you can see the callback code is the same as the original replace expression, the only difference being that references such as \\1 are replaced with array accesses like $matches[1].

like image 27
Jon Avatar answered Oct 06 '22 15:10

Jon


All in all, the best solution is to avoid upgrading PHP to version 5.5, as it is no more compatible with Symfony 1.4

If you have both Symfony 2 and 1.4 versions in a development environment, you may want to be able to switch your PHP version, as nicely described here.

If you really need to, it is possible to setup two different versions of PHP running on the same Apache server at the same time: this will need some more configuration, the above link explains that too.

Alternative HOT FIX:

With a couple of updates in the Symfony code, I can get most of my webpages running in dev. Of course, it would be dangerous to apply this in production, as the "deprecated" error may turn up again at any time, arising from another Symfony library.

In myproject/lib/vendor/symfony/lib/response/sfWebResponse.class.php on line 409, I have now (commented code is original Symfony code):

  protected function normalizeHeaderName($name)
  {
    // return preg_replace('/\-(.)/e', "'-'.strtoupper('\\1')", strtr(ucfirst(strtolower($name)), '_', '-'));    

    return preg_replace_callback(
                  '/\-(.)/', 
                  function ($matches) {
                    return '-'.strtoupper($matches[1]);
                  }, 
                  strtr(ucfirst(strtolower($name)), '_', '-')
        );
  }

And in myproject/lib/vendor/symfony/lib/util/sfToolkit.class.php on line 362 we get:

  public static function pregtr($search, $replacePairs)
  {
    // return preg_replace(array_keys($replacePairs), array_values($replacePairs), $search);
    foreach($replacePairs as $pattern => $replacement)
        $search = preg_replace_callback(
                    $pattern, 
                    function ($matches) use ($replacement){
                        if(array_key_exists(1, $matches)){ $replacement = str_replace("\\1", $matches[1], $replacement);}
                        if(array_key_exists(2, $matches)){ $replacement = str_replace("\\2", $matches[2], $replacement);}
                        return $replacement;
                    }, 
                    $search
                );
    return $search;
  }

Use at your own risks :)

like image 30
mika Avatar answered Oct 06 '22 15:10

mika