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, пока не выйдет какой-нибудь серьезный патч. Что вы думаете ? Любая альтернатива?


person mika    schedule 06.08.2013    source источник
comment
возможный дубликат Замените модификатор preg_replace() e на preg_replace_callback   -  person Jon    schedule 06.08.2013
comment
@Jon Основная проблема здесь заключается в том, чтобы заставить Symfony 1.4 работать с PHP 5.5. В этом смысле я бы сказал, что это не дубликат (и я бы сохранил исходное название :o). Что вы думаете ? Я согласен, что замена preg_replace на preg_replace_callback — это способ сделать это, но предыдущий поток не полностью решает эту проблему...   -  person mika    schedule 06.08.2013
comment
@mika: Возможно... дело в том, что вопрос начинается с того, как я могу изменить код, на что я ответил, но затем переходит к вопросам об исправлениях и возможных будущих обновлениях, для которых ресурсы разработчика Symfony будут место, куда можно пойти. (Я вижу, что 1.4.x не видел никаких коммитов в течение 8 месяцев, поэтому я не ожидаю, что это когда-либо будет исправлено в стандартной версии Symfony). Возможно, меня увлекла часть строки 429, слишком специфичная. В любом случае ИМХО цель вопроса должна быть уточнена.   -  person Jon    schedule 06.08.2013
comment
@Jon: Конечно, я начал пытаться ответить на свой вопрос еще до того, как закончил формулировать его. Mea culpa (позвольте мне переформулировать). Ваш ответ был очень полезен для изучения. Теперь в более широком контексте редактирование кода Symfony 1.4 не кажется самым простым решением.   -  person mika    schedule 06.08.2013
comment
Многие устаревшие функции preg_replace() symfony1 исправлены в форке symfony1 @j0k. Чтобы узнать, как исправить эти проблемы, посмотрите этот пулл-реквест: github.com/LExpress/symfony1/ вытащить/26/файлы   -  person John Kary    schedule 13.03.2017


Ответы (7)


Ошибки не отображаются в prod, если вы не включили отладку в index.php. Их также можно удалить в dev, сняв флаг E_DEPRECATED в settings.yml:

dev:
  .settings:
    error_reporting:  <?php echo ((E_ALL | E_STRICT) ^ E_DEPRECATED)."\n" ?>
person flm    schedule 30.08.2013
comment
Одно быстрое и простое решение :) Большое спасибо! - person mika; 02.09.2013
comment
-1 Это не решение! Вы должны исправить код, и комментарии ниже сделали это возможным. xtech - исправил sfToolkit.class.php и mika - исправил sfWebResponse.class.php (он также предлагает исправить второй файл, но у меня это не работает, выдавая фатальную ошибку) - person Radamanf; 06.08.2014
comment
Дублируйте stackoverflow. ком/вопросы/21091955/ - person Radamanf; 06.08.2014
comment
Определенно не лучшее решение, чтобы скрыть то, что не работает, просто сказать: теперь это работает! -_- - person j0k; 02.09.2014
comment
Как предложено ниже, но немного скрыто, лучший вариант в настоящее время использовать поддерживаемую сообществом версию symfony1... Это своего рода symfony 1.5: github.com/LExpress/symfony1 Полностью совместим с php 5.5 и 5.6. - person Zoltan; 25.02.2015
comment
Спасибо @szines за размещение этой ссылки. Я поддерживаю наше сложное производственное приложение Symfony 1.4, и это может выиграть нам немного времени. Хотел бы я, чтобы SensioLabs давным-давно разместили ссылку на этот форк, я впервые о нем слышу. - person ybull; 11.06.2015

По сути, вам нужно взять аргумент замены из вызова 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].

person Jon    schedule 06.08.2013
comment
Это выглядит действительно хорошо и дает исправление для сообщения об ошибке. Далее я получаю ту же проблему с myproject/lib/vendor/symfony/lib/util/sfToolkit.class.php в строке 362. Это означает, что код нужно будет обновить в разных местах в версии Symfony I. use... :/ @jOk А, хорошо, это соответствует вашему комментарию выше :) Вы имеете в виду, что это возможность для меня поучаствовать в исходном коде Symfony? Звучит хорошо :) - person mika; 06.08.2013
comment
Мне пришлось изменить только /lib/vendor/symfony/lib/response/sfWebResponse.class.php, спасибо! - person Arkadiusz Cieśliński; 10.02.2020

В общем, лучшее решение — не обновлять PHP до версии 5.5, так как он больше не совместим с Symfony 1.4.

Если у вас есть версии Symfony 2 и 1.4 в среде разработки, вы можете захотеть иметь возможность переключать версию PHP, как хорошо описано здесь.

Если вам действительно нужно, можно настроить две разные версии PHP, работающие на одном и том же сервере Apache одновременно: для этого потребуется дополнительная настройка, ссылка выше также объясняет это.

Альтернативный ГОРЯЧИЙ ИСПРАВЛЕНИЕ:

С парой обновлений в коде Symfony я могу запустить большинство своих веб-страниц в dev. Конечно, было бы опасно применять это в продакшене, так как ошибка «deprecated» может появиться снова в любое время, вызванная другой библиотекой 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;
  }

Используйте на свой страх и риск :)

person mika    schedule 06.08.2013
comment
Зачем вам нужно модифицировать функцию pregtr? Он не использует /e .. И, кстати, мы знаем, что есть открытая проблема по этому поводу< /а>. - person j0k; 19.08.2013
comment
@jOk pregtr поставляется с двумя аргументами, которые используются в вызове preg_replace. Оказывается, в аргументе $search иногда используется параметр /e, поэтому здесь необходимо изменить вызов preg_replace. Точно так же текущий код Symfony работает с максимум двумя совпадающими шаблонами в вызовах pregtr, и по этой причине предлагаемый мной патч работает нормально (только с array_key_exists 1 и 2, а не с 3, 4, 5 и т. д.). ...). Если есть более общий способ справиться с этим, буду рад его увидеть :) О, и спасибо за проблему. Это хорошо знать. - person mika; 21.08.2013
comment
Ошибка не отображается в prod, если вы не включили отладку в index.php. Их также можно удалить в dev, сняв флаг E_DEPRECATED в settings.yml: ‹?php echo ((E_ALL | E_DEPRECATED) ^ E_DEPRECATED).\n ?› - person flm; 26.08.2013
comment
@flm: это быстрое решение, которое я искал. Если вы разместите свой совет в сообщении, я отмечу его как правильный ответ. Огромное спасибо ! - person mika; 29.08.2013
comment
@flm Отключать все сообщения без звука - плохая практика, вам лучше сразу исправить такие небольшие проблемы, спасибо поиску в Google и людям, которые сделали это раньше :). - person Arkemlar; 12.07.2016

ИСПРАВЛЕНИЕ для метода 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;
}
person macatapichon    schedule 26.03.2014

Существует версия Symfony от сообщества, которая поддерживает и исправляет старый код:

https://github.com/LExpress/symfony1

person Kevin    schedule 29.08.2014

Альтернативное ИСПРАВЛЕНИЕ для метода 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;
}
person sadikoff    schedule 18.03.2014

person    schedule
comment
Вставленный контент из blog.jakoubek.cz/symfony-1-4-deprecated -e-modifier на этот раз, надеюсь, это поможет. - person ImLeo; 12.08.2014
comment
Это самый полный ответ здесь - person Nate; 26.01.2016
comment
Это очень плохо для чтения и понимания. Ссылка на github будет очень кстати. - person Arkemlar; 21.12.2016