J'ai récemment mis à niveau PHP de la version 5.3.27 à 5.5.0. Tout fonctionne bien dans mon projet Symfony 2.3.2 et je peux profiter des dernières fonctionnalités de PHP.
Maintenant, lorsque je reviens à mon autre projet Symfony 1.4.16, une erreur PHP s'affiche sur le fait que preg_replace est obsolète avec le modificateur/e.
Je ne trouve aucune référence à cette erreur dans les forums: Quelqu'un at-il déjà eu ce problème? Existe-t-il un type de correctif que je pourrais appliquer hors de la boîte? Une mise à niveau vers Symfony 1.4.20 va-t-elle résoudre ce problème?
Le message d'erreur va comme ceci:
Obsolète: preg_replace (): le modificateur/e est obsolète, utilisez preg_replace_callback à la place de /myproject/lib/vendor/symfony/lib/response/sfWebResponse.class.php à la ligne 409
Une façon de procéder consiste à modifier le code comme recommandé dans le message et dans le manual . Comment puis-je changer mon expression preg_replace en un appel preg_replace_callback?
Toute aide/suggestion sera la bienvenue.
MODIFIER:
À ce jour, il n'y a pas de correctif pour cela (et Symfony 1.4.20 ne résout pas le problème). La solution consiste à remplacer les appels en échec de preg_replace par l'appel correspondant à preg_replace_callback dans la source, ce qui se fait facilement dans la classe sfWebResponse (merci pour l'allusion Jon). Maintenant la prochaine occurrence manquante est un peu plus complexe, malheureusement ... Et d'autre part, nous devrions probablement rechercher les utilisations de preg_replace avec l'option/e pour déterminer où Symfony risque de tomber en panne. Ce qui donne pas mal de résultats: o
Donc ... Ma conclusion serait que les utilisateurs de Symfony 1.4 ne feraient pas mieux de mettre à jour PHP vers la version 5.5 tant qu'un correctif sérieux ne sera pas publié. Qu'est-ce que tu penses ? Une alternative?
Les erreurs n'apparaissent pas dans prod sauf si vous avez activé le débogage dans index.php . Il est également possible de les supprimer dans dev en désactivant le drapeau E_DEPRECATED dans settings.yml :
dev:
.settings:
error_reporting: <?php echo ((E_ALL | E_STRICT) ^ E_DEPRECATED)."\n" ?>
En gros, vous devez prendre l'argument de remplacement de l'appel preg_replace
et le factoriser en une expression PHP appropriée, puis transformer cette expression en corps d'une fonction qui sera utilisée comme rappel à l'appel preg_replace_callback
équivalent .
Dans votre cas, le code pertinent est
return preg_replace('/\-(.)/e', "'-'.strtoupper('\\1')", /* input */)
Alors tu ferais ça comme
$callback = function($matches) {
return '-'.strtoupper($matches[1]);
};
return preg_replace_callback('/\-(.)/', $callback, /* input */)
Comme vous pouvez constater que le code de rappel est identique à l'expression de remplacement d'origine, la seule différence est que les références telles que \\1
sont remplacées par des accès à un tableau tels que $matches[1]
.
FIX pour la méthode normalizeHeaderName dans /lib/vendor/symfony/lib/response/sfWebResponse.class.php à la ligne 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);
}
FIX pour la méthode pregtr dans /lib/vendor/symfony/lib/util/sfToolkit.class.php on line 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;
}
Globalement, la meilleure solution consiste à éviter de mettre à niveau PHP vers la version 5.5, car celle-ci n'est plus compatible avec Symfony 1.4.
Si vous disposez des versions Symfony 2 et 1.4 dans un environnement de développement, vous pouvez vouloir changer de version PHP, comme décrit joliment here .
Si vous en avez vraiment besoin, il est possible de configurer deux versions différentes de PHP s'exécutant simultanément sur le même serveur Apache: il faudra davantage de configuration, le lien ci-dessus l'explique également.
Alternative à chaud:
Avec quelques mises à jour dans le code Symfony, la plupart de mes pages Web sont exécutées dans dev. Bien entendu, il serait dangereux de l'appliquer en production, car l'erreur "obsolète" peut se reproduire à tout moment, à partir d'une autre bibliothèque Symfony.
Dans mon projet/lib/vendor/symfony/lib/response/sfWebResponse.class.php à la ligne 409, j'ai maintenant (le code commenté est le code Symfony d'origine):
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)), '_', '-')
);
}
Et dans monprojet/lib/vendor/symfony/lib/util/sfToolkit.class.php à la ligne 362, nous obtenons:
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;
}
Utilisez à vos risques et périls :)
Il existe une version communautaire de Symfony qui gère et corrige l’ancien code:
Alternative FIX pour pregtr method dans/lib/vendor/symfony/lib/util / sfToolkit.class.php en ligne 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;
+ }
}
--