El modificador e, correspondiente a la constante PCRE PREG_REPLACE_EVAL, era utilizado en expresiones regulares junto a la función preg_replace() cuando era necesario ejecutar PHP para generar el string de salida.

Para hacer su trabajo, el modificador e echaba mano de la función eval(), una función muy delicada en lo que a seguridad se refiere, y por ello el modificador e fue deprecidado en PHP 7. En su lugar se recomienda utilizar preg_replace_callback(), ya que nos permite definir un callback propio donde podemos ejecutar PHP si es necesario, pero sin necesidad de recurrir a eval().

¿Por qué ha sido depreciado? 3g3h3j


Vamos a ver un sencillo ejemplo para explicarlo; imaginemos esta expresión donde pasamos un título a letras mayúsculas aplicando la función strtoupper()al string de salida de preg_replace():
$title = "<h1>The /e modifier</h1>";
$title = preg_replace(
    '#<h([1-6])>(.*?)</h\1>#e',
    '"<h$1>" . strtoupper("$2") . "</h$1>"',
    $title
);
Lo que hace preg_repalce() es:

  1. Busca el patrón definido en la expresión regular (primer parámetro) en la variable $title
  2. Captura los fragmentos que coincidan con los conjuntos entre paréntesis: ([1-6]) y (.*?), y los numera por orden de aparición: 1, 2, etc (0 sería la coincidencia completa).
  3. Duelve el string del segundo parámetro sustituyendo las referencias $1, $2, etc, por los correspondientes valores capturados en el paso anterior.
Si observamos el string de salida, podemos ver que se ejecuta una función, strtoupper() , pero la función está contenida en un string. Para que funciones PHP contenidas en un string sean ejecutadas, hay que pasar ese string a la funcnón eval(), y eso es lo que hace el modificador e.

Imaginemos ahora el mismo código pero tomando el valor de $title desde un input:
$title = $__GET['title'];
$title = preg_replace(
    '#<h([1-6])>(.*?)</h\1>#e',
    '"<h$1>" . strtoupper("$2") . "</h$1>"',
    $title
);
Si el introduce código PHP en el string de entrada, ese código sería ejecutado debido al uso que comentábamos de la función eval(). Es un punto débil de seguridad, ese es el motivo por el que el modificador e fue depreciado en PHP 7, y motivo por el que la propia función eval() se debe utilizar con muchísima precaución.

Alternativa: preg_replace_callback() 1u3i6w


Para conseguir el mismo resultado que con preg_replace() y el modificador e, pero sin el riesgo de utilizar eval(), se puede utilizar preg_replace_callback(), función que nos permite definir un callback propio dónde podemos manejar los valores capturados y generar el string de salida como deseemos, incluyendo la ejecución de código.
 
El ejemplo anterior quedaría:
$title = $__GET['title'];
$title = preg_replace_callback(
    '#<h([1-6])>(.*?)</h\1>#',
    function ( $matches ) {
        $output = '<h' . $matches[1] . '>' . strtoupper( $matches[2] ) .'</h' . $matches[1] . '>';
        return $output;
    },
    $title
);
O un poco mejor:
$title = $__GET['title'];
$title = preg_replace_callback(
    '#<h([1-6])>(.*?)</h\1>#',
    function ( $matches ) {
        $output = '<h%1$d>%2$s</h%1$d>';
        return sprintf(
            $output,
            $matches[1],
            strtoupper( $matches[2] )
        );
    },
    $title
);
En pocas palabras, si se necesita ejecutar PHP en el string de salida de preg_replace(), hay que utilizar preg_replace_callback().

En versiones inferiores a PHP 7 se puede utilziar preg_replace() y el modificador e, funcionará, pero por ser un potencial agujero de seguridad, mejor utilizar preg_replace_callback() incluso en versiones inferiores a PHP 7.
Compartir

Mi nombre es Alexander fundador y CEO, y me gusta llamarme un Geek. Amo la informática, tecnología y todo lo que está relacionado con ella. Inicié este sitio con la intención de compartir conocimientos como cursos en línea, tutoriales y videotutoriales. Estoy muy entusiasmado con la información que he descubierto y compartido hasta el momento. La verdad es que lo he hecho con el mayor de los gustos. Así es, soy un Geek con una visión para compartir conocimiento. Leer mas... 6b6s