Aprende cómo hacer que la versión 1.4.20 de un proyecto heredado de Symfony sea totalmente compatible sin errores para una versión más reciente de PHP (5.5 y 5.6).

Cómo hacer que un proyecto Symfony 1.4.20 sea totalmente compatible con PHP 5.5 o 5.6 (elimine las advertencias obsoletas: preg_replace())

A veces, debido a la cantidad de código y los costos de renovación, muchos proyectos web todavía se ejecutan en plataformas PHP antiguas (bueno, no tan antiguas, por ejemplo 5.3) con marcos heredados como Symfony 1.x. Por sí solo, el código no tiene nada de malo, ya que funciona bastante bien, sin embargo, es difícil encontrar documentación para él. Además con el tiempo, las personas descubren fallas de seguridad en los frameworks y pueden ser explotadas, por eso siempre es recomendable avanzar con versiones más nuevas del framework. Con Symfony, la cosa no fue tan fácil ya que el flujo de trabajo cambió significativamente, lo que significa que es necesario cambiar todo el código fuente.

Si no está dispuesto a reescribir una gran aplicación creada en Symfony 1.4.20, aún puede ejecutarla en versiones más nuevas de PHP que, a cambio, son más seguras que las versiones anteriores. El único problema es que verá constantemente una advertencia en desuso en su proyecto debido a un uso inseguro de preg_replace.

¿Qué causa el problema específicamente?

El problema se desencadena en el proyecto debido al modificador / e para expresiones regulares. El modificador / e en preg_replace está obsoleto en PHP 5.5 porque se puede usar para realizar la ejecución de código arbitrario, como se indica en  POSIX Pattern Modifiers Docs . Entonces, el problema es que dicho patrón se usa en muchos archivos fuente de Symfony 1.4.20 para simplemente "Camelizar" algunas cadenas y es por eso que ves la advertencia gráficamente en tu proyecto.

Las advertencias no aparecen en el entorno de producción a menos que haya habilitado la depuración index.php (solo aparecen en  frontend_dev.php), por lo que, en teoría, ofrecer una solución simple (soluciones rápidas) es posible eliminar esas advertencias para que no aparezcan simplemente ignorando las E_DEPRECATEDbanderas. Puedes lograr esto en el settings.ymlarchivo de tu proyecto:

# YourProject/apps/YourApp/config/settings.yml
dev:
    .settings:
        error_reporting:  <?php echo ((E_ALL | E_STRICT) ^ E_DEPRECATED)."\n" ?>

Esto ocultará inmediatamente esas advertencias para que no aparezcan en el entorno de desarrollo, sin embargo , esta no es la forma más correcta de proceder, ya que en el futuro, esas funciones se pueden eliminar y su aplicación ya no funcionará.

¿Cómo solucionarlo correctamente?

Para solucionar este problema correctamente siguiendo las buenas prácticas de hacer que el código dure al menos un par de versiones más, es solucionar el error implementando la función preg_replace_callback donde se necesite. Deberá modificar un total de 7 archivos del código fuente de su Symfony 1.4.20:

1. /symfony/lib/util/sfToolkit.class.php

En este archivo, deberá agregar el siguiente método al final de la clase:

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;
}

Este método se utilizará para los otros archivos más adelante.

2. /symfony/lib/util/sfInflector.class.php

En este archivo cerca de la línea 28, reemplace la función camelize con el siguiente código:

public static function camelize($lower_case_and_underscored_word)
{
    $tmp = $lower_case_and_underscored_word;
    
    return sfToolkit::camelize($tmp);
}

3. /symfony/lib/response/sfWebResponse.class.php

En este archivo cerca de la línea 407, reemplace normalizeHeaderNamecon el siguiente código:

protected function normalizeHeaderName($name)
{
    return preg_replace_callback('/\-(.)/', function ($matches) { return '-'.strtoupper($matches[1]); }, strtr(ucfirst(strtolower($name)), '_', '-'));
}

4. /symfony/lib/plugins/sfPropelPlugin/lib/form/sfFormFilterPropel.class.php

En este archivo cerca de la línea 264, reemplace la función camelize con el siguiente código:

protected function camelize($text)
{
    return sfToolkit::camelize($text);
}

5. /symfony/lib/plugins/sfDoctrinePlugin/lib/form/sfFormFilterDoctrine.class.php

En este archivo cerca de la línea 324, reemplace la función camelize con el siguiente código:

protected function camelize($text)
{
    return sfToolkit::camelize($text);
}

6. /symfony/lib/form/addon/sfFormObject.class.php

En este archivo cerca de la línea 279, reemplace la función camelize con el siguiente código:

protected function camelize($text)
{
    return sfToolkit::camelize($text);
}

7. /symfony/lib/command/sfCommandManager.class.php

En este archivo cerca de la línea 109, cambie el siguiente código ejecutado en la instrucción else if:

// hackear para dividir argumentos con espacios: --test = "con algunos espacios"
$arguments = preg_replace('/(\'|")(.+?)\\1/e', "str_replace(' ', '=PLACEHOLDER=', '\\2')", $arguments);
$arguments = preg_split('/\s+/', $arguments);
$arguments = str_replace('=PLACEHOLDER=', ' ', $arguments);

Con este nuevo código:

// hackear para dividir argumentos con espacios: --test = "con algunos espacios"
$arguments = preg_replace_callback('/(\'|")(.+?)\\1/', function($matches) {
    return str_replace(' ', '=PLACEHOLDER=', $matches[2]);
}, $arguments);
$arguments = preg_split('/\s+/', $arguments);
$arguments = str_replace('=PLACEHOLDER=', ' ', $arguments);

Después de cambiar todos los archivos, borre el caché de su proyecto y acceda a él en su navegador nuevamente. Ahora las advertencias ya no deberían aparecer.

Que te diviertas ❤️!


Interesado en la programación desde los 14 años, Carlos es un programador autodidacta, fundador y autor de la mayoría de los artículos de Our Code World.

Conviertete en un programador más sociable

Patrocinadores