Недавно я обновил 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 в sourche, что легко сделать в классе sfWebResponse (спасибо за подсказку Jon). Теперь следующее неудачное появление немного сложнее, к сожалению … И, с другой стороны, нам, вероятно, придется использовать grep для использования preg_replace с опцией / e, чтобы узнать, где Symfony может сломаться. Это дает немало результатов: o
Итак … Мое заключение состояло бы в том, что пользователям Symfony 1.4 лучше не обновлять PHP до версии 5.5 до тех пор, пока не появится какой-то серьезный патч. Как вы думаете ? Любая альтернатива?
Ошибки не отображаются в prod, если вы не включили debug в index.php . Также можно удалить их в dev, отключив флаг E_DEPRECATED в settings.yml :
dev: .settings: error_reporting: <?php echo ((E_ALL | E_STRICT) ^ E_DEPRECATED)."\n" ?>
В основном то, что вам нужно сделать, это взять аргумент замены из вызова preg_replace
и 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 */)
Как вы можете видеть, код обратного вызова совпадает с исходным выражением replace, единственное отличие заключается в том, что ссылки, такие как \\1
, заменяются обращениями к массиву, такими как $matches[1]
.
В общем, лучшим решением является отказ от обновления PHP до версии 5.5, поскольку он не более совместим с Symfony 1.4
Если у вас есть версии Symfony 2 и 1.4 в среде разработки, вы можете захотеть переключить свою версию PHP, как это хорошо описано здесь .
Если вам действительно нужно, можно одновременно настроить две разные версии PHP, работающие на одном сервере Apache: для этого потребуется еще одна конфигурация, приведенная выше ссылка также объясняет это.
Альтернативный HOT FIX:
Имея пару обновлений в коде 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("/('::'\.)?([az]*)\('\\\\([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, которая поддерживает и исправляет старый код:
Альтернативный FIX для метода 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("/('::'\.)?([az]*)\('\\\\([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; + } } --