Corregir errores `ereg is deprecated` en PHP 5.3

Desde principios de noviembre del año pasado (2010/11/10) tenemos ya disponible RedHat 6 (seguimos esperando por CentOS 6) que trae PHP 5.3.2, serie (5.3.x) con la cual ya hemos estado trabajando en nuestras plataformas de desarrollo (Fedora) desde hace poco más de un año, justamente para buscar estar preparados para los casos que ya hemos empezado a experimentar:

He actualizado mi servidor Linux (de RedHat/CentOS 5 a RedHat/CentOS 6) y al menos una de mis aplicaciones web (basada en PHP) ha dejado de funcionar mostrándome errores del tipo `Function ereg() is deprecated`.

La explicación es simple, como fue anunciado con anticipación (los logs de versiones previas de PHP ya mostraban un mensaje indicando la futura depreciación de las funciones tipo `ereg`) estas funciones fueron retiradas para siempre en PHP 5.3. Una de las razones principales para esta decisión es que eran mucho más lentas y su sintaxis menos familiar que las alternativas Funciones PCRE.

Afortunadamente la solución es también simple, aunque puede resultar demorada y tediosa, dependiendo de qué tan extensivamente se usaron las Funciones (que han sido depreciadas) de expresiones regulares POSIX dentro de la aplicación. Veamos entonces la solución, revisando independientemente cada una de las funciones depreciadas de uso más común:

Migrando ereg():

ereg('\.([^\.]*$)', $this->filename, $extension);

reemplazarla por:

preg_match('/\.([^\.]*$)/', $this->filename, $extension);

Nótese que he encerrado el patrón de coincidencia \.([^\.]*$) entre / / (slashes), mismos que son delimitadores de patrón. Si el patrón contuviera slashes (una URL por ejemplo) entonces quizás quieras usar el delimitador # (sharp) en lugar del slash.

Migrando eregi():

Siguiendo la lógica seguramente buscaríamos la función pregi_match(), que debería ser la versión no sensible a mayúsculas/minúsculas de preg_match(). Sin embargo no existe nada parecido, pues en su lugar se trabaja con los modificadores de expresión regular. Básicamente para volver a preg_match insensible a mayúsculas/minúsculas deberemos anexar la i luego del delimitador de patrón. Entonces, para cambiar:

eregi('\.([^\.]*$)', $this->filename, $extension);

reemplazarla por:

preg_match('/\.([^\.]*$)/i', $this->filename, $extension);

Migrando ereg_replace():

$this->filename = ereg_replace('[^A-Za-z0-9_]', '', $this->filename);

Reemplazarla por:

$this->filename = preg_replace('/[^A-Za-z0-9_]/', '', $this->filename);

Nuevamente, sólo agregué los slashes como delimitadores al patrón.

Migrando eregi_replace():

Nuevamente aplicamos la i como modificador de expresión regular, al igual que en el caso de eregi() explicado anteriormente:

$this->filename = eregi_replace('[^A-Za-z0-9_]', '', $this->filename);

Reemplazarla por:

$this->filename = preg_replace('/[^A-Za-z0-9_]/i', '', $this->filename);

Con lo cual se han cubierto los cambios necesarios en las Funciones de Expresiones Regulares POSIX de uso más frecuente. La filosofía se mantiene intacta para el resto de funciones no detalladas aquí pero que pertenecen a la misma librería como split() y spliti().

Finalmente, aprovecho para hacer notar que éste es sólo uno de los cambios/mejoras que pueden provocarte problemas al actualizar la versión del SO y/o de PHP. Sin embargo como ya te imaginarás, no es el único, y otro de los que se presentarán con regular frecuencia es que por defecto en PHP 5.3 ya no se soportan los short open tags para iniciar código PHP, es decir si al inicio (o en cualquier parte) de uno de tus scripts PHP estaba algo como esto:

// Código de ejemplo de short Open Tag
<?
  $pi = 3.1416;
  // Más código aquí
  // y más aún acá

Deberás reemplazar <? por el tag completo que es <?php así:

// Código de ejemplo del Open Tag completo
<?php
  $pi = 3.1416;
  // Más código aquí
  // y más aún acá

Si experimentas problemas adicionales a los indicados, sería excelente que los comentes aquí para completar el artículo con sus respectivas soluciones!

Suerte!

 

28 comentarios:

  1. Hola Salvador,

    No conozco mucho sobre PHPnuke así que no podría ayudarte mucho, pero recomiendo que mires los logs del servidor web (error_log típicamente) para tratar de determinar el posible problema. Lo que describes suele ser causado por permisos de acceso de escritura de los archivos de sesión, pero podría ser algo más.

    Suerte!
    Paul

  2. hola yo quisiera saber por que cuando configuro PHPnuke queda configurado y todo entro al panel de administracion pero cuando doy para modificar algo siempre me manda de regreso a pedir usuario y contraseña del administrador. en pocas palabras no me deja hacer nada.. si puedo entrar al panel pero al dar clic en cualquier modulo me regresa a pedir usuario y pass del admin y asi siempre

  3. Hola José,

    Cuando usas preg_match entras a usar las PCRE – Perl Compatible Regular Expressions por lo que la expresión que tienes en la variable $pattern, debes encerrarla en slashes (/…/), algo así:

    $pattern="/[?() \/&#\,\;\.$@+]/g"

    La g al final significa “global” y permite que la coincidencia aplique para toda la cadena ($fname en este caso). Finalmente, no puedo garantizar que la expresión regular siga funcionando exactamente como antes, pues podrían haber diferencias entre POSIX (usada por ereg_replace) y PCRE (usada por preg_replace). Pruébale y espero todo funcione adecuadamente!

  4. Alguien que me pueda ayudar… tengo un sistema de clasificados que está en php y mi servicio de hosting actualizó su versión de php y en mi sistema surgieron varios errores por versión obsoleta, ya corregí varias líneas pero hay una que no le encuentro, es la siguiente:

    $valid_file=ereg_replace($pattern,”_”,trim($fname));

    La función ereg_replace está obsoleta y se la cambié por preg_replace pero me da el siguiente error:

    Warning: preg_replace(): Compilation failed: nothing to repeat at offset 0

    Ya le probé diferentes funciones pero me sigue dando error.

    La porción de código completa donde está la línea del error es la siguiente.
    (la línea del error es la núm 3)

    function GetValidFileName($fname){
    $pattern=”[?() \/&#\,\;\.$@+]”;
    $valid_file=preg_replace($pattern,”_”,trim($fname));
    $valid_file=strtolower($valid_file);
    $valid_file=str_replace(“‘”,””,$valid_file);
    $valid_file=str_replace(‘”‘,”,$valid_file);
    $valid_file=str_replace(“-“,”_”,$valid_file);
    $valid_file=str_replace(“__”,”_”,$valid_file);
    $valid_file=str_replace(“__”,”_”,$valid_file);
    $valid_file=str_replace(“__”,”_”,$valid_file);
    if (substr($valid_file,-1)==”_”) {
    $valid_file=substr($valid_file,0,-1);
    }
    if (substr($valid_file,0,1)==”_”) {
    $valid_file=substr($valid_file,1,strlen($valid_file));
    }

    De antemano agradezco a quién me ayude a resolver este error, muchas gracias!

  5. Hola Carlos,

    Según la version de PHP que tengas el problema puede ser justamente el que estás usando eregi en lugar de preg_match (con el modificador ‘i’). Cualquier duda adicional me comentas.

    Salu2
    Paul

  6. Hola qué tal, intenté reemplazar, pero no me sale, debo cambiar

    if(eregi($who[1], $buffer)) {

    Agradecería su ayuda… gracias…

  7. Hola qué tal, intenté reemplazar, pero no me sale, debo cambiar

    if(eregi($who[1], $buffer)) {

    Gracias…

  8. Todo lo que pongas en realidad es una expresión regular, siempre debe ir entre los slashes, en el ejemplo que planteas debería ir como: /index\.php/ porque en el otro caso podría coincidir con “index_php” por ejemplo!

  9. Hola José,

    Sobre el tema de las comillas dobles o sencillas, en general no hay diferencia, excepto cuando la cadena contiene ciertos caracteres que pueden hacer que obtengas un resultado no esperado. En lo personal uso comillas dobles sólo cuando necesito que se procesen las secuencias de escape o se puedan embeber variables, por ejemplo:

    $var = 33;
    echo 'La variable es:\n $var';
    echo "La variable es:\n $var";

    produce (en el mismo orden):

    La variable es:\n $var
    La variable es:
    33

    En el caso de usar comillas dobles, el backslash (\) y el signo de dólar ($) son interpretados para generar una salida diferente a si se usan comillas simples (o apóstrofos) en cuyo caso el \ y el $ son exactamente eso.

    Sobre el tema de agregar // para el patrón, sí, es obligado pues son los delimitadores de la cadena de la expresión regular que define el patrón. Recuerda que las funciones que contienen “preg” sugieren que usan expresiones regulares.

  10. queria ampliar mi duda, los slashes se ponen aunque el patron no sea una expresion regular y que sea por una cadena de carecteres por ejemplo un nombre de archivo “index.php” tambien lo cambio a “/index.php/”?

  11. estoy haciendo la migracion de las funciones de ereg y demas, pero tengo duda porque tu pones comillas sencillas y en el codigo que tengo viene con comillas dobles, pregunta: es indistinto? es decir aunque tenga comillas dobles debo de agregar el / / para el patron? aunque el patron sea “.” un punto.gracias por ayudar.

  12. Muchas gracias si funciona

  13. Excelnet muchas gracias por publicar

  14. Hola Nellim,

    El error que veo es que en lugar del signo ‘$‘ pusiste una ‘S‘, es decir el primer parámetro de la primera llamada a preg_replace dice: SmosConfig_dbprefix y debería decir: $mosConfig_dbprefix, a no ser que SmosConfig_dbprefix sea una constante definida en algún lugar aterior del código…

    Espero que te sirva!

  15. Hola soy novato y en otras expresiones me ha funcionado ok el sustituir ereg_replace por preg_replace (con //añladidos).Pero con la siguiente expresion no lo logro
    if (isset($mosConfig_dbprefix)&&strlen($mosConfig_dbprefix)>0 $table=preg_replace(SmosConfig_dbprefix,”,$table);preg_replace(“/n/”,””,$table
    tal como ahora esta escrita devuelve el error siguiente;
    [Mon Dec 02 17:00:16 2013] [error] [client 5.10.83.3] PHP Warning: preg_replace() [function.preg-replace]: Delimiter must not be alphanumeric or backslash
    y si en el primer preg_replace coloco los slashes devuelve el siguiente error: PHP parse error:syntax error,unexpected ‘/’,expecting ‘)’.
    alguien puede prestarme ayuda.Gracias anticipadas

  16. Excelente De Riviera, qué bueno que te haya servido y hayas podido solucionar tu problema!

  17. Gracias por el aporte, funcionandome la web perfectamente en el servidor donde la tengo alojada, al probarla en el servidor local para hacer unos cambios empezó a darme este tipo de errores que em dejó extrañado, investigando di con tu muy bien explicada solución, gracias.

    Un saludo.

  18. Con tus instrucciones me animé a corregir una aplicación viejita corriendo PHP 5.4 y MySQL 5.5.
    ¡Funcionó!
    Gracias

  19. Excelente aporte!! Sirve de muchoinvestigar de ves en cuando!! 🙂 saludos

  20. muchas gracias por la publicación y la explicación del eregi() primero sustituí directo por el preg_match y me mostró warnings luego hice el cambio //i y salió perfect.

    gracias otra vez.

  21. Excelente aporte, lo malo que actulice un servidor en produccion sin saber las consecuencias que me hiba a traer con esto de las actulizaciones de PHP.

    Soy novato, pero dañando se aprende 🙂

  22. gracias por la ayuda a mi me sirvio agregando la barra quedando de esra manera:

    ((preg_match(“/]*script*\”?[^>]*>/”,

    notese q agregue / al principio y al final

  23. Gracias Toja, qué bueno que haya podido ser útil y qué bueno, que al menos por esta vía sepa que sigues por ahí!!!

    Salu2
    don pool

  24. doble felicitacion, una por ofrecer la respuesta clara y sencilla y otra ser el primer (bien merecido) resultado de google
    muchisimas gracias don pool!!

  25. Qué bueno que te haya sido útil!

  26. Hola mil gracias por este post tan completo con las soluciones a las complicaciones que da la actualización de PHP, he solucionado todo los problemass…

    saludos

  27. Excelente Sergio! saber que los problemas con que me topé y sus soluciones le facilitan la vida a alguien me anima a seguir “buscando problemas” 😉

  28. Muchas gracias, tenia problemas con eregi() en una pequeña aplicación Ajax, y esta solución me ha funcionado

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.