18

我最近将 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

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

任何帮助/提示都将受到欢迎。

编辑:

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

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

4

7 回答 7

37

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

dev:
  .settings:
    error_reporting:  <?php echo ((E_ALL | E_STRICT) ^ E_DEPRECATED)."\n" ?>
于 2013-08-30T16:18:25.887 回答
14

基本上,您需要做的是从preg_replace调用中获取替换参数并将其分解为适当的 PHP 表达式,然后将该表达式作为函数的主体,该函数将用作等效preg_replace_callback调用的回调。

在您的情况下,相关代码

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

所以你会这样做

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

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

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

于 2013-08-06T10:21:22.023 回答
11

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

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

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

替代热修复:

通过对 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;
  }

使用风险自负:)

于 2013-08-06T16:54:06.933 回答
11

修复第 407 行 /lib/vendor/symfony/lib/response/sfWebResponse.class.php 中的 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;
}
于 2014-03-26T13:17:10.107 回答
8

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

https://github.com/LExpress/symfony1

于 2014-08-29T16:21:03.693 回答
5

第 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;
}
于 2014-03-18T09:24:13.417 回答
0
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;
+   }
 }
--
于 2014-08-11T23:59:10.953 回答