Ayer estuve trasteando con PHP 5.3. Resulta que en la configuración por defecto está deshabilitada la opción de short_open_tag.
Esta opción es la que permite escribir código php tal que <?=”algo”?> en vez de tener que escribirlo como <?php echo “algo”?>. Vamos, algo MUY deseable desde mi punto de vista.
Creo que la gente de PHP ha metido un tanto la pata aquí, ya que todo viene por la ambiguedad al parsear documentos xml que empiezan con <?xml. En fin, lo voy a dejar, porque esta es otra historia.
Resulta que tengo una clase llamada jview que se encarga de manejar y cargar las vistas, y quería que se puedan seguir usando los short tags en esas vistas. Al final las vistas que maneja jview son templates PHP. Te puedes hacer una idea si piensas que al final es como un template en WordPress.
Por poner un ejemplo rápido, dado el siguiente código en PHP
<?php echo "hello"?> <?= "world"?>
Cuando short_open_tags está habilitado, la salida que produce PHP es:
hello world
Sin embargo si short_open_tags=”Off”, entonces PHP produce la siguiente salida:
hello <?= "world"?>
En fin, que tenía dos alternativas para solucionar mi problema:
- Copiar el archivo de vista que se intenta cargar a un fichero temporal, reemplazando los ‘<?=’ por ‘<?php ‘, ejecutando el fichero modificado, borrar el fichero
- Hacer un parser de código PHP en PHP que previamente reemplace los ‘<?=’ por ‘<?php ‘
Como uno es como es, he hecho el parser ;D
Lo mejor de todo es que han sido sólo 20 minutos!! Menos de lo que me esperaba!
Aquí está el código:
function include_emulating_short_tags ($viewFile)
{
// Alternate method for making <?= valid
$raw = file_get_contents ($viewFile);
$raw = str_replace ('<?=', '<?php echo ', $raw);
$html = '';
$phptokens = @token_get_all ($raw);
$mode = 'text';
$phpcode = '';
foreach ($phptokens as $ptoken)
{
if (($mode == 'text') && is_array ($ptoken) && ($ptoken[0] === T_OPEN_TAG)) {
$mode = 'php';
continue;
}
if (($mode == 'php') && is_array ($ptoken) && ($ptoken[0] === T_CLOSE_TAG)) {
ob_start();
eval ($phpcode . ';');
$html .= ob_get_contents();
ob_end_clean();
$mode = 'text';
$phpcode = '';
continue;
}
if ($mode == 'text') {
$html .= is_array ($ptoken) ? $ptoken[1] : $ptoken;
}
else {
$phpcode .= is_array ($ptoken) ? $ptoken[1] : $ptoken;
}
}
if (($mode == 'php') && ($phpcode !== '')) {
ob_start();
eval ($phpcode);
$html .= ob_get_contents();
ob_end_clean();
}
return $html;
}Al final, la variable $html que se devuelve, es la que contiene el supuesto código HTML que se mostraría.
Si hicieramos un include_emulating_short_tags con el código inicial y short_open_tags=0, seguiría saliendo “hello world”. El único inconveniente que le veo a esta forma, es que las variables de PHP tipo __FILE__, no sacarían el valor esperado. Aunque de todos modos esto tendría fácil arreglo, con otro str_replace
English
27 Comments on "Emular short tags en PHP cuando short_open_tag = off"