Blog de Israel Viana

Plantillas PHP: cuestión de rendimiento

2 de abril de 2009

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");

?>

Compartir en Twine Delicious Facebook Twitter

5 comentarios

Gravatar de gu
gu
el 9 de noviembre de 2009 a las 18:29

Hay un artículo del 2005, que si bien es ligeramente más avanzado, quizás deberias leer.

http://www.cristalab.com/tutoriales/creacion-y-uso-de-plantillas-o-templates-en-php-c132l/

Gravatar de Isra
Isra
el 10 de noviembre de 2009 a las 14:20

@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.

Gravatar de enigmart
enigmart
el 26 de noviembre de 2009 a las 06:34

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;
}
}

Gravatar de Isra
Isra
el 27 de noviembre de 2009 a las 09:29

@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/

Gravatar de enigmart
enigmart
el 27 de noviembre de 2009 a las 14:31

Es sierto lo que dices, ¿Por que tomar un bus ala casa de tu tia? si ella vive alado.

Gracias =D


Escribe tu opinión

Nombre:
E-mail: (no se mostrará)
Sitio web:
Por favor, suma 8 + 7:
Comentario:
israelviana.es es propiedad de Israel Viana, escrito en Murcia (España). Puedes ponerte en contacto conmigo a través de la dirección de e-mail .com.
Información en RDF Metadatos Dublin Core Creative Commons License