He 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"); ?>
@gu Gracias por el enlace. El sistema que desarrolla el artículo de Cristalab es un parser propio. Como es habitual en Cristalab, el artículo me ha decepcionado sobremanera, por varias razones:
a) El sistema que presentan tiene las desventajas de los parser (rendimiento, tener que aprender un sublenguaje nuevo, etc), pero sin la potencia de Smarty (¿bucles? ¿arrays? ¿clases? ni se menciona).
b) El código fuente huele mal (eval("$this->mihtml = ‘$this->mihtml’;"); ????).
En definitiva, que para usar un sistema de plantillas uso Smarty que es más potente y está más testeado.
La librería que presento en este artículo tiene carácter pedagógico, es decir, no es un código para usar en proyectos reales. Funcionalmente ofrece un espacio de nombres seguro (algo parecido a CssDispatcher pero con funciones) para escribir plantillas en PHP. Las plantillas en PHP tienen mayor rendimiento son más potentes (puedes utilizar todo lo que te ofrece PHP) y no requieren aprender un nuevo lenguaje.
o,o? como se te hace este sistema de plantillas
class template
{
public $tpl;
public function __construct($file)
{
$this->tpl = file_get_contents($file);
}
public function SetVars($vars, $content)
{
$this->tpl = str_replace(‘{‘.$key.’}', $content, $this->tpl);
}
public function __toString()
{
return $tpl->tpl;
}
}
@enigmart Poco funcional. ¿Puedes construir bucles? ¿Llamar a clases estáticas? Te aconsejo que no reinventes la rueda. Si quieres la misma funcionalidad que Smarty, usa Smarty. Además, si tu clase tiene 15 líneas, mientras Smarty tiene miles… sospecha que algo le faltará.
De todos modos… ¿por qué hacer plantillas utilizando {variable} en lugar de <?php echo $variable ?> ? Después de haber utilizado Smarty intensivamente, personalmente me decanto por plantillas de PHP puro. Aquí tienes algunas razones para ello:
http://www.israelviana.es/blog/Post/74/5-razones-para-no-usar-smarty-o-similares/
Es sierto lo que dices, ¿Por que tomar un bus ala casa de tu tia? si ella vive alado.
Gracias =D
Estimado, tu codigo me ha sido de gran ayuda para comprender estos conceptos, aun que aun soy muy novato con el concepto de plantillas.
Tengo un problema con un template que carga una funcion con xajax para guardar un campo en un BBDD(el campo es para inscribirse al newsletter), el problema esk sin ocupar template tengo un archivo con html y php, donde esta la pagina a mostrar y la funcion en xajax.
EL problema es que no puedo cargar el xajax con template, me dice que el obtejo xajax ya lo cargo.
me puedes dar una mano??
SAludos! y muchas gracias!!