Mostrando entradas con la etiqueta plantillas. Mostrar todas las entradas
Mostrando entradas con la etiqueta plantillas. Mostrar todas las entradas

domingo, 23 de diciembre de 2007

Plantillas en PHP (IV)

Cuarta parte de esta serie. Como había dicho vamos a finalizar con el ejemplo e incluir el paginador en la plantilla principal.


Podríamos, como dije en el anterior post, incluir el paginador en nuestra plantilla haciendo un include del archivo que contiene la plantilla. Podríamos pensar que si todas las plantillas están en la misma carpeta no tenemos que especificar la ruta de la plantilla paginador(¿podemos poner simplemente: include "paginador.phpt";?), pero esto no es así. Como vimos, la plantilla principal en última instancia se carga con un include por lo tanto tendrá como path el del archivo que la haya invocado. Esto es un problema ya que si la plantilla principal puede ser invocada desde scripts en diferentes carpetas la ruta del include del paginador debería variar! Para solventar esto añadiremos un método __toString al objeto Template:

function __toString(){
$this->dump();
return "";
}

Ojo, este método no devuelve una cadena de texto, sino que hace un echo de la plantilla. Es decir, no tendría sentido hacer $cadena=$miPlantilla->__toString() ya que $cadena quedaría vacía. Se que esto no es del todo ortodoxo pero veremos que es una forma muy buena de representar objetos en una plantilla.

Esto nos permitirá crear ambas plantillas por separado de modo que especificamos las rutas de la plantillas desde el script que las va a usar:

$miPlantilla=new Template("plantillas/miPlantilla.phpt");
$paginador=new Template("plantillas/paginador.phpt");

Ahora en nuestra plantilla principal añadimos debajo de la tabla:

<?=$PAGINADOR?>

y en nuestro código PHP haremos:

$miPlantilla->set("PAGINADOR",$paginador);

De esta forma conseguimos incluir el paginador en la plantilla principal de manera elegante.

A continuación veremos como nos quedaría nuestra plantilla principal:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title><?=$TITULO?></title>
<style type="text/css">
#paginador{
}
#paginador a.pagina{
}
#paginador a.pagina:hover{
}
#paginador a.pagina:visited{
}
</style>
</head>
<body>
<table>
<thead>
<tr><th>campo 1</th><th>campo 2</th></tr>
</thead>
<tbody>
<? foreach($DATOS AS $D): ?>
<tr><td><?=$D->CAMPO1?></td><td><?=$D->CAMPO2?></td></tr>
<? endforeach ?>
</tbody>
</table>
<?=$PAGINADOR?>
</body>
</html>

Si nos fijamos en la sección style he referenciado todos los estilos al id paginador de forma que estos estilos no van a afectar al resto de la página. Tendremos que tener esto en cuenta para no definir ningún otro elemento con id="paginador", ya que los id deben ser únicos.

Hemos dicho en el anterior post que para indicar la página a mostrar usaríamos la variable $_GET["pagina"]. Por lo que si no está definida tendremos que mostrar la primera página y en caso contrario la que nos indique la variable. Veamos entonces la parte de código PHP:

<?php
$num_por_pagina=10;
$pagina=(isset($_GET["pagina"])?$_GET["pagina"]:1);
$desplazamiento=$num_por_pagina*($pagina-1);

$miPlantilla=new Template("plantillas/miPlantilla.phpt");
$miPlantilla->set("TITULO","KROWORK: Anotaciones de PHP (página ".$pagina.")");
$miPlantilla->set("PAGINADOR",$paginador=new Template("plantillas/paginador.phpt"));

list($num)=mysql_fetch_row($result=mysql_query("SELECT COUNT(*) FROM mitabla"));
mysql_free_result($result);

$paginador->set("NUM_PAGINAS", ceil($num/num_por_pagina) );

$result=mysql_query(
"SELECT micampo1 as CAMPO1, micampo2 as CAMPO2 FROM mitabla LIMIT ".$desplazamiento.",".$num_por_pagina
);
while($obj=mysql_fetch_object($result)) $miPlantilla->setArray("DATOS",$obj);

$miPlantilla->dump();
?>

Es sencillo, legible y tenemos separada la parte de presentación de la lógica de la aplicación.

Otra mejora sería cambiar en la plantilla del paginador el src de las imágenes que hacen de botones de "página siguiente" y "página anterior" por dos variables. Si usamos, por ejemplo $URL_FLECHA_IZQUIERDA y $URL_FLECHA_DERECHA, podremos especificar distintas imágenes según el script que use la plantilla y además evitamos problemas con las rutas como sucedía con el include de la plantilla paginador en la principal.

LEER MÁS……

lunes, 17 de diciembre de 2007

Plantillas en PHP (III)

En los dos anteriores artículos hemos definido un modo de crear plantillas utilizando el motor PHP y hemos visto un pequeño ejemplo de uso. En este post mostraré como realizar una plantilla más elaborada a partir de la que ya hemos visto añadiéndole una plantilla paginador.


Siguiendo con el ejemplo de los anteriores post, si tenemos muchos registros en la base de datos deberíamos dividir su visualización en páginas. Para navegar entre ellas podemos poner unos botones de "alante" y "atrás" o poner un paginador. Un paginador muestra los enlaces a las primeras páginas, a las vecinas de la actual y a las últimas páginas, además de los botones "anterior" y "siguiente".

Para probar esta plantilla sólo tendremos que cargarla con un objeto Template y establecer la variable NUM_PAGINAS:

<?php
include "/classes/Template.class.php";

$tmplt=new Template("platillas/paginador.phpt");
$tmplt->set("NUM_PAGINAS",20);
@$tmplt->dump();
?>


La plantilla en cuestión es la siguiente, aunque el código es muy complejo no es necesario entenderlo para usarla, como ya hemos visto:

<?
$CENTRO=2; //numero de paginas a cada lado de la página seleccionada ...k-2,k-1,k,k+1,k+2...
$LADO=3; //número de primeras paginas 1,2,3... y de ultimas...n-2, n-1, n

//Preparamos la URL siguiente
$PAGINA=(empty($_GET["pagina"])?1:$_GET["pagina"]);
unset($_GET["pagina"]);
$URL_PAGINA=$_SERVER["PHP_SELF"]."?".http_build_query($_GET);
?>
<div id="paginas">
<? if($NUM_PAGINAS>1): ?>

<!-- BOTON PAGINA ANTERIOR -->
<? if($PAGINA>1): ?>
<a href="<?=$URL_PAGINA?>&amp;pagina=<?=($PAGINA-1)?>" class="pagina">
<img src="imagenes/flecha_izq" alt="Página anterior" />
</a>
<? endif ?>

<!-- ENLACES A LAS PRIMERAS PAGINAS -->
<? for($i=1;$i<$LADO+1 && $i<$NUM_PAGINAS+1 && $i<$PAGINA-$CENTRO;$i++): ?>
<a href="<?=$URL_PAGINA?>&amp;pagina=<?=$i?>" class="pagina">
<?=$i?>
</a>
<? endfor ?>

<!-- SEPARADOR -->
<? if( $PAGINA>$LADO+$CENTRO+1 ): ?>
...
<? endif ?>

<!-- PAGINAS VECINAS A LA ACTUAL -->
<? for( $i=((($PAGINA-$CENTRO)>0)?($PAGINA-$CENTRO):1); $i<$NUM_PAGINAS+1 && $i<$PAGINA+$CENTRO+1; $i++ ): ?>
<? if($i==$PAGINA): ?>
<?=$i?>
<? else: ?>
<a href="<?=$URL_PAGINA?>&amp;pagina=<?=$i?>" class="pagina">
<?=$i?>
</a>
<? endif ?>
<? endfor ?>

<!-- SEPARADOR -->
<? if($NUM_PAGINAS>$PAGINA+$CENTRO+$LADO): ?>
...
<? endif ?>

<!-- ENLACES A LAS ULTIMAS PAGINAS -->
<? if( $NUM_PAGINAS>$PAGINA+$CENTRO ): ?>
<? for( $i=((($NUM_PAGINAS-$LADO+1)<=($PAGINA+$CENTRO))?($PAGINA+$CENTRO+1):($NUM_PAGINAS-$LADO+1)); $i<$NUM_PAGINAS+1; $i++ ): ?>
<a href="<?=$URL_PAGINA?>&amp;pagina=<?=$i?>" class="pagina">
<?=$i?>
</a>
<? endfor ?>
<? endif ?>

<!-- BOTON PAGINA SIGUIENTE -->
<? if($PAGINA<$NUM_PAGINAS): ?>
<a href="<?=$URL_PAGINA?>&amp;pagina=<?=($PAGINA+1)?>" class="pagina">
<img src="imagenes/flecha_der.gif" alt="Página siguiente" />
</a>
<? endif ?>
<? endif ?>
</div>

Como es de espera estaremos accediendo al script que muestra la lista a través de una llamada GET. La plantilla se encarga de regenerar la URL de esta llamada (con todas sus variables) añadiendo la variable "pagina" para indicar(obviamente) la página a la que se desea acceder. Esto estrictamente no debería estar en la plantilla y la variable URL_PAGINA deberíamos establecerla nosotros desde fuera de la plantilla, pero vamos a utilizar este atajo ya que tenemos las funciones PHP a nuestra disposición y esto nos simplifica mucho las cosas.

¿Pero como incluirla en la plantilla de la lista? Pues con un include, pero esto y otros detalles sobre los CSS de la plantilla lo dejamos para el próximo post.

LEER MÁS……

jueves, 13 de diciembre de 2007

Plantillas en PHP (II)

Hemos visto en el anterior post que no es necesario aprender la sintaxis de ningún lenguaje de plantillas para poder trabajar con ellas. Una sintaxis reducida del PHP será más que suficiente para disfrutar de sus ventajas.


En este post vamos a definir la clase Template; a través de un objeto de esta clase se carga la plantilla y se le da valores a las variables:

<?php
class Template{
private $VARS=array();
private $archivo;

function __construct($archivo){
$this->archivo=$archivo;
}
//establecemos las variables simples de la plantilla
public function set($nombre,$valor){
if($valor===NULL) unset($this->VARS[$nombre]);
else $this->VARS[$nombre]=$valor;
}
public function setArray($nombre,$valor){
if(empty($this->VARS[$nombre])) $this->VARS[$nombre]=array();
$this->VARS[$nombre][]=$tmp;
}
public function get($nombre){
return $this->VARS[$nombre];
}

public function dump($buffer=false){
if($buffer) ob_start();
if(!empty($this->VARS)) foreach($this->VARS as $variable=>&$valor)
$$variable=$valor;
include($this->archivo);
if($buffer) return ob_get_clean();
}

function __clone() {
foreach($this->VARS as $k=>$v)
if(is_object($v)) $this->VARS[$k]=clone $this->VARS[$k];
}
}
?>

Veamos como utilizarla. Supongamos que hemos guardado la plantilla del anterior post en el archivo "miPlantilla.phpt" si queremos ponerle el título solo tendremos que hacer:

<?php
$miPlantilla=new Template("plantillas/miPlantilla.phpt");
$miPlantilla->set("TITULO","KROWORK: Anotaciones de PHP");
?>

Ahora veamos como crear el array $DATOS de la plantilla a partir de una consulta a la base de datos:

$result=mysql_query("SELECT micampo1 as CAMPO1, micampo2 as CAMPO2 FROM mitabla");
while($obj=mysql_fetch_object($result)) $miPlantilla->setArray("DATOS",$obj);
?>

Y por último mostramos los datos:

<?php
@$miPlantilla->dump();
?>

Utilizamos @ para ocultar los posibles errores/warnings de la plantilla, ya que va a ser habitual que para simplificar comprobemos la existencia de las varibles con una expresión del tipo: <? if($VAR): ?> ... <? endif ?>. Si no hemos definido $VAR se producirá un warning que de esta forma no se mostrará aunque tengamos el reporte de errores al máximo. Evidentemente mientras probamos la plantilla no pondremos la @ para poder detectar los errores.

Como dije en el post anterior, no es raro crear plantillas con archivos xml's. La construcción de un xml nodo a nodo a través de la extensión DOM de PHP es enormemente tediosa. Una forma mucho más fácil de hacerlo es creando una plantilla (ojo: si utilizas short tags deberás hacer uso del truco del post anterior), rellenarla y al final:

<?php
file_put_contents("mi_nuevo_archivo.xml",$miPlantilla->dump(true));
?>

Al pasar true al método dump() hacemos que en lugar de mostrarse el resultado se devuelva en forma de string.

Como vemos las plantillas son muy versátiles, muy fácil de usarlas, de crearlas y al estar escritas en PHP su procesamiento es de lo más rápido que os podais encontrar. Hasta la próxima.

LEER MÁS……

viernes, 16 de noviembre de 2007

Plantillas en PHP (I)

Tras siglos desde mi último post me he decidido a retomar mis escritos con otra serie dedicada a las plantillas. Este primer artículo lo dedicaré a dar una visión general sobre el tema, veremos porqué son útiles y en qué nos ayudan. En los post siguientes propondré una implementación propia de un sistema de plantillas.


Mucha gente, entre la que me incluyo, empezó a programar PHP como un lenguaje de scripting insertado dentro del código HTML. Resultaba muy intuitivo extender las funcionalidades de tu página incluyendo pequeños trozos de código PHP.

El problema surgió cuando a medida que añadimos más funcionalidades el código de nuestras páginas se convierte en El Laberinto del Minotauro. Encontrar y corregir errores tanto HTML/JavaScript como PHP se hace enormemente tedioso al tener todo el código mezclado. Este tipo de escritura de código es altamente interdependiente además de compartir lógica y presentación la mismas variables.
Esta situación es mala de cara a la gestión de errores, mala frente a futuras modificaciones, mala porque no podemos aprovechar código de un proyecto a otro y mala porque no podemos dividir el trabajo entre diseñador y programador.

¿Como hacer código menos interdependiente?


Pensemos como sería una pagina HTML con el mínimo código PHP, para representar el típico resultado de una búsqueda en nuestra base de datos:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title><?=$TITULO?></title>
</head>
<body>
<table>
<thead>
<tr><th>campo 1</th><th>campo 2</th></tr>
</thead>
<tbody>
<? foreach($DATOS AS $D): ?>
<tr><td><?=$D->CAMPO1?></td><td><?=$D->CAMPO2?></td></tr>
<? endforeach ?>
</tbody>
</table>
</body>
</html>


Primero, SÍ, utilizo short tags, para activarlas deberás editar tu php.ini poniendo short_open_tag=1. Pero, un momento, seguro que habréis visto en más de un sitio que no se deben utilizar las short tag que son la reencarnación del diablo y otras lindeces, veamos porqué:

  1. No se deben utilizar las short tags porque producen problemas si queremos hacer un include de un xml. Los archivos xml empiezan con <?xml y por lo tanto el PHP (con short tags activadas) interpreta que ahí empieza un bloque PHP. Esto se soluciona si en lugar de empezar de ese modo el xml lo empezamos así: <<? ?>?xml . ¿Supone esto un gran problema para no hacer uso de las short tags? Cada uno tendrá su opinión.

  2. No es raro hacer un include de un xml sobre todo si vamos a utilizar un sistema de plantillas basado en PHP, que en última instancia hará un include de la plantilla, y si ésta es un xml surgirá el problema.


A mi personalmente no me parece un gran problema si a cambio puedo utilizar <?= ?> que resulta un gran aliado para legibilidad de las plantillas, en todo caso cada uno es libre de utilizar <?php echo.

Dicho esto diré también que ya tenemos nuestra primera plantilla PHP. Metan ese código en un archivo, guárdenlo en UTF-8 y pónganle una extensión del tipo .phpt. A partir de ahora diferentes scripts podrán utilizar la misma plantilla o un mismo script utilizar plantillas diferentes. Además, se requieren unos mínimos conocimientos de PHP para hacer una plantilla por lo que fácilmente podrá hacerlas un diseñador mientras nosotros nos dedicamos a la miga de la aplicación y que se pelee él con el JavaScript, el DOM y las CSS (sí teneis la gran fortuna de tener un buen diseñador a mano).

Pero, ¿como instanciar esa plantilla y rellenar los huecos? paciencia, lo veremos en la próxima entrada.

LEER MÁS……