XForms
Recopilo aqui, una pequeña aproximación a lo que nos deparara a los desarrolladores, con el uso de este lenguaje y mis conclusiones.

Esta imagen es muy familiar a casi todos nosotros, cada tienda virtual tiene un formulario html que se parece a este, lo mas comodo seria tener un objeto que integrase estas variables y su funcionamiento conjunto. Esto no es nada nuevo, ASP.NET, permite generar “objetos” que se renderizan como una unidad a pesar de estar compuestos por subelementos html. Tambien sucede con JSP con las beans y la logica de estos objetos tambien se integra dentro de la unidad. Lo malo de esta forma de trabajar, bajo mi punto de vista, es la continua ida y venida al servidor, para validar los mismos datos antes de ser enviados.
<xforms:model>
<xforms:instance>
<ecommerce xmlns=”">
<method/>
<number/>
<expiry/>
</ecommerce>
</xforms:instance>
<xforms:submission action=”http://example.com/submit” method=”post” id=”submit” includenamespaceprefixes=”"/>
</xforms:model>
Que luego en el servidor podriamos recoger en el mismo orden y jerarquia:
<ecommerce>
<method>cc</method>
<number>1235467789012345</number>
<expiry>2001-08</expiry>
</ecommerce>
Por otro lado tenemos los elementos que definen la interface, que captura los datos que especificamos arriba, que podemos cargar desde fuera como un archivo XSD
<select1 ref="method">
<label>Select Payment Method:</label>
<item>
<label>Cash</label>
<value>cash</value>
</item>
<item>
<label>Credit</label>
<value>cc</value>
</item>
</select1>
<input ref="number">
<label>Credit Card Number:</label>
</input>
<input ref="expiry">
<label>Expiration Date:</label>
</input>
<submit submission="submit">
<label>Submit</label>
</submit>
h2. Validaciones
Capitulo mucho mas complejo parece el de los eventos y validaciones. Pero parece que por fin podremos confiar plenamente en el navegador para validar los datos con el ahorro que esto supone de recursos y lineas de codigo de servidor.
 Conclusión
XForms es una recomendación de la w3c(World Wide Web Consortium) y pronto lo veremos en los navegadores. Parece un acercamiento hacia la promesa de la web semantica, Podemos compartir y reutilizar nuestro codigo mas que nunca, nuestro codigo dependera del dispositivo solo en la presentacion no en los datos, mas comodidad para usar microformatos que ayuden a buscadores a reconocer la información…
Cachear BLOBS y LONGTEXT de Base de Datos
La idea que subyace esta tecnica es la idea de usar sin abusar el contenido dinamico, las partes que menos cambian en un sitio seran las que se actualizen con menos frecuencia, y a la inversa.
Esta tecnica se esta perfeccionando, en las ultimas tecnologias de servidor. En asp.net tenemos una libreria especializada en tecnicas de cache ( System.Web.Caching ) . En Php, el proceso de cacheo, no viene en ninguna libreria nativa, pero el proceso no es muy complicado y la adaptabilidad es total.
En los portales online, se muestran articulos con tamaños de imagenes completamente diferentes dependiendo del contexto, Cada articulo puede tener muchas imagenes, y ademas se deberia permitir la posibilidad de ver la imagen del articulo en el tamaño original de la foto ( 1024×768 aproximadamente). Estos requisitos no permiten que exista la posibilidad de guardar un numero determinado de formatos para cada foto ( thumbnail, mediano y grande), Porque limita el diseño del portal y porque a la larga, cada foto que se descarga en la web es una costosa conexion que nos acerca a la puerta de salida de nuestro servidor de alojamientos.
La tecnica de caché de servidor, nos permite almacenar información en el sistema de directorios de nuestro servidor, para evitarnos conexiones innecesarias. Dentro de esta modalidad hay muchas formas de crearnos nuestra propia caché, yo os muestro la que estoy llevando a cabo, extraida en gran parte de este interesante articulo. Basicamente:
El cliente hace una petición
El servidor detecta si existe un archivo con la información facilitada en su petición. dos opciones:
- Si existe recoge el contenido de este fichero y lo escribe en el documento.
- Si no existe, hace una consulta a la base de datos, crea un fichero con el resultado y escribe la información de la base de datos en el documento. La proxima vez que alguien haga la misma petición, dispondra de esta información sin acceder a la base de datos.
Aqui muestro el sencillo codigo con el que se puede hacer este proceso:
///recogemos una la peticion del cliente
$id=$_GET['id'];
$cachefile ="cache/imagen-{$id}.jpg";
if (file_exists($cachefile)) { //detectamos si existe el fichero y si existe, lo escribimos
$fp = fopen($cachefile, 'r');
echo fread($fp,filesize($cachefile));
fclose($fp);
exit;
}
//si no se hubiera parado antes realizamos la consulta
$sql = "SELECT foto FROM imagenes WHERE id_foto=$id";
if(!($result = mysql_query ($query, $conexion))) { exit(); }
$data = @ mysql_fetch_array($result);
mysql_free_result($result);
if (!empty($data['foto'])) {
$size=strlen($data['foto']);
//Abrimos un buffer
ob_start();
header("Content-Type: image/jpeg");
header("Content-Length: $size");
echo $data['foto'];
$fp = fopen($cachefile, 'w');
//escribimos el fichero recien creado con los contenidos del buffer fwrite($fp, ob_get_contents());
fclose($fp);
//cerramos el buffer
ob_end_flush();
}
Hasta aqui no existe ninguna ventaja con respecto a guardar una imagen en directorio en vez de en base de datos. Con el siguiente ejemplo quizá te convenza:
$id=$_GET['id'];
include("../includes/config.php");
$cachefile = "cache/miniatura-{$id}.jpg";
if (file_exists($cachefile)) {
$fp = fopen($cachefile, 'r');
echo fread($fp,filesize($cachefile));
fclose($fp);
exit;
}
$query = "SELECT foto, ancho,alto FROM imagenes WHERE id_foto=$id";
if(!($result = mysql_query ($query, $conexion))) exit();
$data = @mysql_fetch_array($result);
if (!empty($data['foto'])) {
//compruebo el tamaño original de la foto
list($ancho,$alto)=array($data['ancho'],$data['alto']);
ob_start();
header("Content-Type: image/jpeg");
$imagen_bit = imagecreatefromstring($data['foto']);
//la transformo en una imagen mas pequeña
$target = imagecreatetruecolor($ancho/4, $alto/4);
imagecopyresampled($target, $imagen_bit, 0, 0, 0, 0, $ancho/4, $alto/4, $ancho, $alto);
imagejpeg($target);
$fp = fopen($cachefile, 'w');
//escribo el fichero fwrite($fp, ob_get_contents());
fclose($fp);
ob_end_flush();
}
El inconveniente de esta manera de trabajar es ¿cuando y como sabemos que se han actualizado los datos?. Para sitios con mucho trafico, se podria plantear el borrado de la cache cada x tiempo, pero ya no seria información “fresca”. Mi alternativa pasa por borrar todos los archivos de cache las imagenes cuando se eliminen y/o modifiquen los articulos relacionados. Para esta tarea tengo una clase que simplifica las tareas comunes relacionadas con la cache y que os muestro aqui. No esta optimizada pero funciona bien, si veis alguna manera de mejorarla os agradeceria que me lo mostraseis, y poder asi publicarlo.
<?php
class cache
{
public static $items_cargados;
public static function borra($item)
{//borra todos los archivos de la carpeta cache que empiecen por $item
$cachefile ="../cache/{$item}*";
$resultado = glob($cachefile);
if ($resultado !== FALSE){
foreach ($resultado as $filename)
{
unlink($filename);
}
}
// if (file_exists($cachefile)) unlink($cachefile);
}
public static function guarda($item, $contenido,$tipo=null)
{//lee $contenido y lo escribe como $item en la carpeta /cache $cachefile ="../cache/$item";
//$size=strlen($contenido);
ob_start();
if ($tipo!=null)header("Content-Type: $tipo");
if($tipo=="image/jpeg")
{
$contenido = imagejpeg($contenido);
}else echo $contenido;
$fp = fopen($cachefile, 'x');
fwrite($fp, ob_get_contents());
fclose($fp);
ob_end_flush();
}
public static function detecta($item)
{//Detecta la existencia del fichero $item en la carpeta /cache
if(cache::$items_cargados==null)cache::$items_cargados=array();
if(array_search($item,cache::$items_cargados)!=false)return true;
$items_cargados[]=$item;
$cachefile ="../cache/$item";
return file_exists($cachefile);
}
public static function carga($item)
{//escribe el archivo en pantalla
$cachefile ="../cache/$item";
include($cachefile);
}
public static function carga_binario($item)
{//Escribe el archivo binario en pantalla
//En este caso no nos serviria el include ya que en ocasiones arrastra simbolos que interpreta como caracteres especiales de php
$cachefile ="../cache/$item";
$fp = fopen($cachefile, 'r');
echo fread($fp,filesize($cachefile));
fclose($fp);
}
}
?>
¿Y como se usa?. Como ejemplo pongo el siguiente archivo que retorna una imagen con la altura que el usuario desee, y un ancho proporcional:
<?php
include("../includes/config.php");
include("../classes/cache.class.php");
if ($id==null)$id=$_GET['id'];
if ($alto==null)$alto=$_GET['alto'];
$id_imagen_unico="imagen{$id}_{$alto}";
if (cache::detecta($id_imagen_unico))
{
cache::carga($id_imagen_unico);
}else{
$query = "SELECT foto, ancho, alto FROM imagenes WHERE id_foto=$id";
if(!($result = mysql_query ($query, $conexion)))
{
exit();
}
$data = @ mysql_fetch_array($result);
mysql_free_result($result);
list($ancho_img,$alto_img)=array($data['ancho'],$data['alto']);
if (!empty($data['foto']))
{
$imagen_bit = imagecreatefromstring($data['foto']);
$target = imagecreatetruecolor($alto*$ancho_img/$alto_img,$alto);
imagecopyresampled($target, $imagen_bit, 0, 0, 0, 0, $alto*$ancho_img/ alto_img, $alto, $ancho_img, $alto_img);
cache::guarda($id_imagen_unico,$target,'image/jpeg');
imagedestroy($imagen_bit);
imagedestroy($target);
}
}
mysql_close($conexion);
?>