【问题标题】:Symfony 1.4 using deprecated functions in php 5.5Symfony 1.4 使用 php 5.5 中已弃用的函数
【发布时间】:2013-08-07 06:55:15
【问题描述】:

我最近将 PHP 从 5.3.27 版本升级到 5.5.0。 在我的 Symfony 2.3.2 项目中一切正常,我可以享受最新的 PHP 功能。

现在,当我回到我的另一个 Symfony 1.4.16 项目时,我收到一个关于 preg_replace 被 /e 修饰符弃用的 PHP 错误。

我在论坛中找不到有关此错误的参考:以前有人遇到过这个问题吗?有没有我可以开箱即用的补丁?升级到 Symfony 1.4.20 会解决这个问题吗?

错误信息是这样的:

已弃用:preg_replace():/e 修饰符已弃用,请在第 409 行的 /myproject/lib/vendor/symfony/lib/response/sfWebResponse.class.php 中使用 preg_replace_callback 代替

一种方法可能是按照消息和manual 中的建议修改代码。 如何将我的 preg_replace 表达式更改为 preg_replace_callback 调用?

非常欢迎任何帮助/提示。

编辑:

到目前为止,还没有针对此问题的补丁(Symfony 1.4.20 没有解决该问题)。解决方案是用源中对 preg_replace_callback 的相应调用替换对 preg_replace 的失败调用,这在 sfWebResponse 类中很容易完成(感谢 Jon 的提示)。现在next failing occurrence 稍微复杂一点,不幸的是……另一方面,我们可能不得不使用 /e 选项来 grep 用于 preg_replace 以找出 Symfony 可能中断的位置。这给出了很多结果:o

所以... 我的结论是 Symfony 1.4 用户最好不要将 PHP 升级到 5.5 版,直到出现一些严重的补丁。你怎么看 ?有什么选择吗?

【问题讨论】:

  • 这个isn't fixed in symfony 1.4.x。您应该自己修补课程。如果您可以在our symfony1 上对您的更改提出拉取请求,那就太棒了:)
  • @Jon 这里的主要问题是让 Symfony 1.4 与 PHP 5.5 一起工作。从这个意义上说,我会说它没有重复(我会保留原来的标题 :o )。你怎么看 ?我同意用 preg_replace_callback 替换 preg_replace 是完成它的方法,但之前的线程并没有完全解决这个问题......
  • @mika:可能......问题是问题以“我如何修改代码”开头,这是我的回答,但随后继续询问补丁和可能的未来更新-- Symfony 开发人员资源将是去的地方。 (我看到 1.4.x 已经有 8 个月没有看到任何提交了,所以我不希望这会在股票 Symfony 中得到修复)。也许我被过于具体的“429行”部分带走了。无论如何,恕我直言,应该澄清问题的目的。
  • @Jon:当然,在我真正完成表述之前,我就开始尝试回答我的问题。 Mea culpa(让我重新表述一下)。您的回答对深入挖掘很有帮助。现在在更大的背景下,编辑 Symfony 1.4 代码似乎不是最简单的解决方法。

标签: php preg-replace symfony-1.4 preg-replace-callback


【解决方案1】:

有一个社区版本的 Symfony 可以维护和修补旧代码:

https://github.com/LExpress/symfony1

【讨论】:

    【解决方案2】:

    修复了 /lib/vendor/symfony/lib/response/sfWebResponse.class.php 第 407 行中的 normalizeHeaderName 方法

    protected function normalizeHeaderName($name)
    {
      //return preg_replace('/\-(.)/e', "'-'.strtoupper('\\1')", 
      strtr(ucfirst(strtolower($name)), '_', '-');
      return str_replace(array('\'$1$3\'','\'$2$4\'','\'$1\'', '\'$2\'', '$1', '$2'),array('$matches[1].$matches[3]','$matches[2].$matches[4]','$matches[1]','$matches[2]','$matches[1]','$matches[2]'),
    $name);
    }
    

    第 360 行 /lib/vendor/symfony/lib/util/sfToolkit.class.php 中 pregtr 方法的修复

    public static function pregtr($search, $replacePairs){
      // return preg_replace(array_keys($replacePairs), array_values($replacePairs), $search);
      foreach($replacePairs as $pattern => $replacement)
      {
        if (preg_match('/(.*)e$/', $pattern, $matches))
        {
          $pattern = $matches[1];
          $search = preg_replace_callback($pattern, function ($matches) use ($replacement) {
            preg_match("/('::'\.)?([a-z]*)\('\\\\([0-9]{1})'\)/", $replacement, $match);
            return ($match[1]==''?'':'::').call_user_func($match[2], $matches[$match[3]]);
          }, $search);
        }
        else
        {
          $search = preg_replace($pattern, $replacement, $search);
        }
      }
      return $search;
    }
    

    【讨论】:

      【解决方案3】:
      Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in lib/vendor/symfony/…This changelog will solve the problem for all symfony 1.4.x. Tested on Symfony 1.4.20
      ---
       lib/vendor/symfony/lib/command/sfCommandManager.class.php     |  4 +++-
       lib/vendor/symfony/lib/form/addon/sfFormObject.class.php      |  2 +-
       lib/vendor/symfony/plugins/sfDoctrinePlugin/lib/form/sfFormFilterDoctrine.class.php  |  2 +-
       lib/vendor/symfony/plugins/sfPropelPlugin/lib/form/sfFormFilterPropel.class.php      |  2 +-
       lib/vendor/symfony/lib/response/sfWebResponse.class.php       |  2 +-
       lib/vendor/symfony/lib/util/sfInflector.class.php             |  5 +----
       lib/vendor/symfony/lib/util/sfToolkit.class.php               | 11 +++++++++++
       7 files changed, 19 insertions(+), 9 deletions(-)
      
      lib/vendor/symfony/lib/command/sfCommandManager.class.php
      @@ -108,7 +108,9 @@ class sfCommandManager
           else if (!is_array($arguments))
           {
             // hack to split arguments with spaces : --test="with some spaces"
      -      $arguments = preg_replace('/(\'|")(.+?)\\1/e', "str_replace(' ', '=PLACEHOLDER=', '\\2')", $arguments);
      +      $arguments = preg_replace_callback('/(\'|")(.+?)\\1/', function($matches) {
      +         return str_replace(' ', '=PLACEHOLDER=', $matches[2]);
      +     }, $arguments);
             $arguments = preg_split('/\s+/', $arguments);
             $arguments = str_replace('=PLACEHOLDER=', ' ', $arguments);
           }
      
      lib/vendor/symfony/lib/form/addon/sfFormObject.class.php
      @@ -278,6 +278,6 @@ abstract class sfFormObject extends BaseForm
      
         protected function camelize($text)
         {
      -    return preg_replace(array('#/(.?)#e', '/(^|_|-)+(.)/e'), array("'::'.strtoupper('\\1')", "strtoupper('\\2')"), $text);
      +    return sfToolkit::camelize($text);
         }
       }
      
      lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/form/sfFormFilterDoctrine.class.php
      @@ -323,7 +323,7 @@ abstract class sfFormFilterDoctrine extends sfFormFilter
      
         protected function camelize($text)
         {
      -    return sfToolkit::pregtr($text, array('#/(.?)#e' => "'::'.strtoupper('\\1')", '/(^|_|-)+(.)/e' => "strtoupper('\\2')"));
      +    return sfToolkit::camelize($text);
         }
      
         protected function getTable()
      
      lib/vendor/symfony/lib/plugins/sfPropelPlugin/lib/form/sfFormFilterPropel.class.php
      @@ -263,6 +263,6 @@ abstract class sfFormFilterPropel extends sfFormFilter
      
         protected function camelize($text)
         {
      -    return sfToolkit::pregtr($text, array('#/(.?)#e' => "'::'.strtoupper('\\1')", '/(^|_|-)+(.)/e' => "strtoupper('\\2')"));
      +       return sfToolkit::camelize($text);
         }
       }
      
      lib/vendor/symfony/lib/response/sfWebResponse.class.php
      @@ -406,7 +406,7 @@ class sfWebResponse extends sfResponse
          */
         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)), '_', '-'));
         }
      
         /**
      
      lib/vendor/symfony/lib/util/sfInflector.class.php
      @@ -28,10 +28,7 @@ class sfInflector
         public static function camelize($lower_case_and_underscored_word)
         {
           $tmp = $lower_case_and_underscored_word;
      -    $tmp = sfToolkit::pregtr($tmp, array('#/(.?)#e'    => "'::'.strtoupper('\\1')",
      -                                         '/(^|_|-)+(.)/e' => "strtoupper('\\2')"));
      -
      -    return $tmp;
      +    return sfToolkit::camelize($tmp);;
         }
      
         /**
      
      lib/vendor/symfony/lib/util/sfToolkit.class.php
      @@ -608,4 +608,15 @@ class sfToolkit
      
           return set_include_path(join(PATH_SEPARATOR, $paths));
         }
      +
      +   public static function camelize($text)
      +   {
      +       if (preg_match('#/(.?)#', $text, $matches)) {
      +           $text = str_replace($matches[0], '::'.strtoupper($matches[1]), $text);
      +       }
      +       if (preg_match('/(^|_|-)+(.)/', $text, $matches)) {
      +           $text = str_replace($matches[0], strtoupper($matches[2]), $text);
      +       }
      +       return $text;
      +   }
       }
      --
      

      【讨论】:

      【解决方案4】:

      第 360 行 /lib/vendor/symfony/lib/util/sfToolkit.class.phppregtr 方法的替代修复

      public static function pregtr($search, $replacePairs)
      {
        // return preg_replace(array_keys($replacePairs), array_values($replacePairs), $search);
        foreach($replacePairs as $pattern => $replacement)
        {
          if (preg_match('/(.*)e$/', $pattern, $matches))
          {
            $pattern = $matches[1];
            $search = preg_replace_callback($pattern, function ($matches) use ($replacement) {
              preg_match("/('::'\.)?([a-z]*)\('\\\\([0-9]{1})'\)/", $replacement, $match);
              return ($match[1]==''?'':'::').call_user_func($match[2], $matches[$match[3]]);
            }, $search);
          }
          else
          {
            $search = preg_replace($pattern, $replacement, $search);
          }
        }
        return $search;
      }
      

      【讨论】:

        【解决方案5】:

        除非您在 index.php 中启用了调试,否则这些错误不会显示在 prod 中。也可以通过在 settings.yml 中取消设置 E_DEPRECATED 标志在 dev 中删除它们:

        dev:
          .settings:
            error_reporting:  <?php echo ((E_ALL | E_STRICT) ^ E_DEPRECATED)."\n" ?>
        

        【讨论】:

        • 快速简便的解决方法 :) 非常感谢!
        • -1 这不是解决方案!您应该修复代码,并在 cmets 下方使其成为可能 xtech - 修复了 sfToolkit.class.php 和 mika - 修复了 sfWebResponse.class.php (他还提供了第二个文件的修复,但它对我不起作用,给出致命错误)
        • 如下建议,但有点隐藏,现在最好的选择是使用社区维护的 symfony1 版本...这是一种 symfony 1.5:github.com/LExpress/symfony1 完全兼容 php 5.5 和 5.6
        • 感谢@szines 发布该链接。我正在维护我们复杂的生产 Symfony 1.4 应用程序,这可能会为我们争取一些时间。我希望 SensioLabs 早在很久以前就提供了指向该分支的链接,这是我第一次听说它。
        【解决方案6】:

        总而言之,最好的解决方案是避免将 PHP 升级到 5.5 版本,因为它不再与 Symfony 1.4 兼容

        如果您在开发环境中同时拥有 Symfony 2 和 1.4 版本,您可能希望能够切换您的 PHP 版本,正如 here 所描述的那样。

        如果你真的需要,可以同时在同一个 Apache 服务器上设置两个不同版本的 PHP:这需要更多的配置,上面的链接也说明了这一点。

        替代热修复:

        通过对 Symfony 代码的一些更新,我可以让我的大部分网页在 dev 中运行。当然,将它应用到生产环境中会很危险,因为“已弃用”错误可能随时再次出现,由另一个 Symfony 库引起。

        在第 409 行的 myproject/lib/vendor/symfony/lib/response/sfWebResponse.class.php 中,我现在有(注释代码是原始 Symfony 代码):

          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)), '_', '-')
                );
          }
        

        在第 362 行的 myproject/lib/vendor/symfony/lib/util/sfToolkit.class.php 中,我们得到:

          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;
          }
        

        使用风险自负:)

        【讨论】:

        • 为什么要修改pregtr函数?它不使用/e .. 顺便说一句,我们知道有an opened issue about that
        • @jOk pregtr 带有两个在 preg_replace 调用中使用的参数。事实证明,$search 参数有时使用 /e 选项,这就是为什么这里需要更改 preg_replace 调用的原因。以同样的方式,当前的 symfony 代码可以在 pregtr 调用中使用最多两个匹配模式,因此我建议的补丁工作正常(只有 array_key_exists 1 和 2,而不是 3、4、5 等...)。如果有更通用的方法来处理这个问题,我会很高兴看到它:) 哦,谢谢你的问题。很高兴知道这一点。
        • 除非您在 index.php 中启用了调试,否则该错误不会显示在 prod 中。也可以通过取消设置 settings.yml 中的 E_DEPRECATED 标志在 dev 中删除它们:
        • @flm:这是我正在寻找的快速解决方案。如果您将您的提示放在帖子中,我会将其标记为正确答案。非常感谢!
        • @flm 将所有消息静音是不好的做法,你最好立即解决这些小问题,感谢谷歌搜索和以前做过的人:)。
        【解决方案7】:

        基本上,您要做的就是从preg_replace 调用中取出替换参数并将其分解为适当的PHP 表达式,然后将该表达式作为函数的主体,该函数将用作对等价@ 的回调987654323@电话。

        在您的情况下,relevant code

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

        所以你会这样做

        $callback = function($matches) {
            return '-'.strtoupper($matches[1]);
        };
        
        return preg_replace_callback('/\-(.)/', $callback, /* input */)
        

        您可以看到回调代码与原始替换表达式相同,唯一的区别是 \\1 之类的引用被替换为 $matches[1] 之类的数组访问。

        【讨论】:

        • 这看起来非常好,并修复了错误消息。现在更进一步,我在第 362 行遇到了与 myproject/lib/vendor/symfony/lib/util/sfToolkit.class.php 相同的问题。这意味着代码需要在 Symfony 版本 I 的各个地方更新使用... :/ @jOk 啊,好吧,这符合你上面的评论:) 你的意思是这是我参与 Symfony 源代码的机会?听起来不错:)
        • 我只需要更改 /lib/vendor/symfony/lib/response/sfWebResponse.class.php,谢谢!
        猜你喜欢
        • 1970-01-01
        • 2018-04-29
        • 1970-01-01
        • 2013-08-22
        • 1970-01-01
        • 2020-04-20
        • 2011-08-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多