Symfony 1.4 использование устаревших функций в php 5.5
Я недавно обновил PHP с версии 5.3.27 до 5.5.0. В моем проекте Symfony 2.3.2 все работает нормально, и я могу наслаждаться новейшими функциями PHP.
Теперь, когда я возвращаюсь к своему другому проекту Symfony 1.4.16, я получаю ошибку PHP о том, что preg_replace устарел с модификатором /e.
Я не могу найти ссылки на эту ошибку на форумах: У кого-нибудь раньше была эта проблема? Есть ли какой-нибудь патч, который я мог бы применить из коробки? Является обновление до Symfony 1.4.20 исправит эту проблему?
Сообщение об ошибке выглядит следующим образом:
Устарело: preg_replace(): Модификатор /e устарел, вместо этого используйте preg_replace_callback в /myproject/lib/vendor/symfony/lib/response/sfWebResponse.class.php в строке 409
Одним из способов может быть изменение кода, как рекомендовано в сообщении и в руководстве . Как я могу изменить выражение preg_replace на вызов preg_replace_callback ?
Любая помощь/подсказка будут очень кстати.
ИЗМЕНИТЬ:
На сегодняшний день для этого нет исправления (и Symfony 1.4.20 не решает проблему). Решение состоит в том, чтобы заменить неудачные вызовы preg_replace соответствующим вызовом preg_replace_callback в источнике, что легко сделать в классе sfwebresponse (спасибо за подсказку, Джон). Теперь следующее неудачное событие, к сожалению, немного сложнее... А с другой стороны, нам, вероятно, пришлось бы grep для preg_replace использует опцию с /e, чтобы узнать, где Symfony может сломаться. Что дает довольно много результатов: o
Итак... Я бы сделал вывод, что пользователям Symfony 1.4 лучше не обновлять PHP до версии 5.5, пока не выйдет какой-нибудь серьезный патч. Как ты думаешь? Есть ли альтернатива?
7 answers
Ошибки не отображаются в prod, если вы не включили отладку в index.php . Также можно удалить их в dev, сбросив флаг E_DEPRECATED в настройках.yml :
dev:
.settings:
error_reporting: <?php echo ((E_ALL | E_STRICT) ^ E_DEPRECATED)."\n" ?>
В основном то, что вам нужно сделать, это взять аргумент замены из вызова 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]
.
В целом, лучшим решением будет избежать обновления PHP до версии 5.5, так как он больше не совместим с Symfony 1.4
Если у вас есть версии Symfony 2 и 1.4 в среде разработки, вы можете захотеть переключить свою версию PHP, как хорошо описано здесь.
Если вам действительно нужно, можно настроить две разные версии PHP, работающие на одном сервере Apache одновременно: для этого потребуется дополнительная настройка, ссылка выше это тоже объясняет.
Альтернативное ГОРЯЧЕЕ ИСПРАВЛЕНИЕ:
С помощью нескольких обновлений в коде Symfony я могу запустить большинство своих веб-страниц в dev. Конечно, было бы опасно применять это в производстве, так как "устаревшая" ошибка может появиться снова в любое время, возникнув из другой библиотеки Symfony.
В myproject/lib/vendor/symfony/lib/response/sfWebResponse.class.php в строке 409 у меня теперь есть (прокомментированный код является оригинальным кодом 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)), '_', '-')
);
}
И в myproject/lib/vendor/symfony/lib/util/sfToolkit.class.php в строке 362 мы получаем:
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;
}
Используйте на свой страх и риск:)
ИСПРАВЛЕНО для метода normalizeHeaderName в /lib/vendor/symfony/lib/response/sfWebResponse.class.php в строке 407
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);
}
ИСПРАВЛЕНИЕ для метода pregtr в /lib/vendor/symfony/lib/util/sfToolkit.class.php на линии 360
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;
}
Существует версия Symfony для сообщества, которая поддерживает и исправляет старый код:
Альтернативное ИСПРАВЛЕНИЕ для метода pregtr в /lib/поставщике/symfony/lib/util/sfToolkit.class.php на линии 360
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;
}
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;
+ }
}
--