Plantillas PHP: cuestión de rendimiento
2 de abril de 2009He leído dos posts bastante viejos (2006 y 2007) del gran Ricardo Galli sobre el rendimiento y escalabilidad de Twitter y los sistemas de plantillas en PHP. En ambos posts las discusiones han sido muy ricas, y me llevan a dos grandes conclusiones: aunque el cache y escalabilidad horizontal son soluciones importantes para la alta disponibilidad de sitios web, es vital escribir buen código. Y en ese sentido, los sistemas de plantillas y los frameworks pueden jugar malas pasadas.
Plantillas PHP, sin pseudo-lenguajes
En posts recientes he hablado de Smarty y de PHPTAL, dos sistemas de plantillas que añaden un lenguaje nuevo a nuestras aplicaciones web, ya cargadas con PHP, SQL, XHTML, CSS, JavaScript y nosecuantas siglas más. Eso significa que, además de la curva de aprendizaje, hay que cargar el proyecto con un parser del pseudo-lenguaje. En el caso de Smarty, dicen ser rápidos, aunque hay un fork del proyecto llamado TemplateLight que dice ser más liviano que su "papá".
Existe un método para utilizar plantillas y no usar sistemas adicionales. Es una sistema sencillo, estúpidamente sencillo, pero eficiente y prácticamente con los mismos beneficios que usar Smarty u otros: plantillas en PHP, embebiendo los códigos en los documentos HTML, pero sin las chapuzas de siempre, separando las capas de lógica y vista.
Podemos crear una pequeña biblioteca de funciones para gestionar plantillas de este tipo y que los nombre de variables no causen conflictos. Voy a hacer algún proyecto con este sistema, a modo de prueba (es lo que tiene ser freelance, puedo usar la tecnología que me dé la gana ;-). Utilizar plantillas en PHP permite separar la presentación de la lógica, pero sin la bajada de rendimiento de los sistemas que parsean plantillas escritas en un pseudo-lenguaje como Smarty, del que ya se ha hablado por aquí. Reconozco que las plantillas PHP no tienen la legibilidad de Smarty o PHPTAL, pero se le acerca bastante.
simpletpl.php (la librería del motor)
<?php
//Directorio donde están las plantillas
define("TPL_DIR", "tpl");
//Array que alojará las variables de las plantillas
$tpl_vars = array();
//Asigna una variable a la plantilla
function tpl_asignar($nombre, $valor) {
global $tpl_vars;
$tpl_vars[$nombre] = $valor;
}
//Devuelve una variable de la plantilla
function tpl($variable) {
global $tpl_vars;
if (isset($tpl_vars[$variable])) return $tpl_vars[$variable];
else trigger_error("La variable '$variable' no existe", E_USER_ERROR);
}
//Carga la plantilla especificada
function tpl_cargar($plantilla) {
global $tpl_vars;
if (file_exists(TPL_DIR)) {
if (file_exists(TPL_DIR . "/$plantilla")) {
include(TPL_DIR . "/$plantilla");
} else trigger_error("La plantilla '$plantilla' no existe", E_USER_ERROR);
} else trigger_error("El directorio de plantillas especificado no existe. Verifique la constante TPL_DIR", E_USER_ERROR);
}
//Indenta un texto al $n - ésimo nivel
function tab($texto, $n) {
return preg_replace('/\n/', "\n" . str_repeat("\t", $n), $texto);
}
?>
inicio.tpl.php (un ejemplo de plantilla cualquiera)
<html>
<head>
<title><?php echo tpl('titulo') ?></title>
</head>
<body>
<h1><?php echo tpl('titulo') ?></h1>
<?php foreach (tpl('posts') as $p) { ?>
<h2><a href="<?php echo $p['url'] ?>"><?php echo $p['titulo'] ?></a></h2>
<div style="color: gray"><?php echo $p['creado'] ?></div>
<?php echo tab($p['cuerpo'], 2) ?>
<?php } ?>
<?php tpl_cargar("pie.tpl.php") ?>
pie.tpl.php (otra plantilla de ejemplo, para ser incluida)
<div style="background: silver; padding: 10px">2008 © Israel Viana</div>
</body>
</html>
index.php (script que obtiene los datos y carga la plantilla)
<?php
include("simpletpl.php");
$conexion = mysql_connect("localhost", "root", "root");
mysql_select_db("blog");
$q = mysql_query("SELECT * FROM posts ORDER BY id DESC LIMIT 5");
$posts = array();
while ($p = mysql_fetch_assoc($q)) {
$p['url'] = "http://www.israelviana.es/post.php?id=" . $p['id'];
$posts[] = $p;
}
tpl_asignar("titulo", "Blog de Israel Viana");
tpl_asignar("posts", $posts);
tpl_cargar("inicio.tpl.php");
?>








