21.2.06

Tutorial de AJAX con PHP y JSON

O como programar el próximo Gmail separando código, base de datos, diseño y presentación de forma natural.
Actualización: Además de este artículo, publiqué uno mas recientemente en
http://thinkcoderepeat.blogspot.com/2006/08/arquitectura-cliente-servidor-con-ajax.html . El código fuente de ese tutorial esta en Google Code y se lo pueden bajar.

Actualización 2: Para los que insisten con este código y tienen un error de "Ajax no esta definido". Deben tener en el mismo directorio los archivos .html, el archivo prototype.js, JSON.php y todos los archivos .php del ejemplo. Suerte!

Todo el mundo envidia la interface de usuario de Gmail. Yo no hubiera usado un webmail aunque me pagaran hasta que los muchachos de google sacaron gmail. Lo revolucionario es su interface limpia y simple y que una vez que entrás a la página parece un solo programa, y no un montón de páginas unidas entre si por links. La responsable de esto es una tecnología llamada AJAX. En este artículo vamos a ver como programar en AJAX usando Javascript y PHP para lograr aplicaciones mas rápidas, mejores interfaces y .
¿Qué es AJAX?


AJAX no es un lenguaje. Es el acrónimo de Asynchronous JavaScript And XML y es una nueva (relativamente) forma de hacer páginas web.
En el corazón de Ajax está el objeto XMLHttpRequest que permite desde javascript obtener el contenido de una url. Usando este objeto desde una página HTML común se puede leer datos de la web, o enviar los datos de un formulario a un servidor sin necesidad de hacer un refresh en la página.

Recordemos como funciona una mini aplicación web tradicional y despues veamos como funcionaría en AJAX.

En web tradicional uno crearía una página HTML con un formulario. Cuando el usuario hace click en el botón de enviar el browser se conecta al servidor, envía los datos y muestra en pantalla la pagina que el servidor devuelve. Esto hace que el browser "salte" a otra página. Además el usuario tiene que esperar que se cargue todo el HTML de la nueva página para verla.

En AJAX pondríamos un código javascript que haría que cuando hacen click en enviar se cree un objeto XMLHttpRequest. La llamada es asyncrónica. Esto significa que se envían los datos y esto no interrumpe al usuario como cuando enviamos un formnulario. En la llamada definimos una función de JavaScript que va a ser llamada cuando el servidor responda. Esta función ("callback") es la que recibe la contestación del servidor y que por ejemplo puede actualizar un texto en la pagina para avisar que los datos se enviaron ok. El browser no cambia de página. La primera ventaja que vemos es que la experiencia del usuario es mucho mas parecida a usar un programa que una página web. Y ahí está el cambio de paradigma. En vez de pensar en función de páginas enlazadas entre si tenemos que pensar en una aplicación, que envía datos y recibe datos.

La siguiente ventaja es la velocidad. En vez de tener que recibir todo el HTML de la página de confirmación nuestro formulario AJAX solo necesita que el server le responda OK o que algo no anduvo.

Prototype

Usar XMLHtppRequest no es muy cómodo y además tendríamos que salvar problemas de compatibilidad entre browsers. Para faclitar las cosas vamos a usar una librería que se encargue de crear el objeto XMLHttpRequest por nosotros. Se llama Prototype se usa en otras librerías muy buenas como Open Rico y Script.aculo.us y en Ruby on Rails.

¿Como se comunica el servidor con mi página?

Como dijimos antes, la X de AJAX viene de XML. Se supone que las respuestas del servidor vienen coificadas en XML. Se puede manejar XML en Javascript, pero a mi modo de ver usar XML para esto es matar moscas con una maza. Procesar el XML y programar el código es un overhead que se puede evitar. Además el XML se puede volver un poco pesado si lo que devolvemos son muchos datos.

JSON al rescate


Cuando lean esto van a preguntarse como no se les ocurrió a ustedes (salvo que sean Douglas Crockford)
Javascript es un lenguaje interpretado, y tiene una función llamada eval() que curiosamente lo que hace es evaluar lo que le pasemos y ejecutarlo. Por ejemplo eval("alert(hola)") hace que se ejecute la función alert("hola"), mostrando un mensaje.

Ahora, la instrucción eval("['a','b']") es perfectamente válida y devuelve un array conteniendo 'a' y 'b'.

JSON es un formato de intercambio de datos alternativo a XML, mucho mas simple de leer, escribir e interpretar. Significa Javascript Object Notation y consiste en escribir los datos en Javascript. Evaluar un array, entero o string escrito como código javascript es trivial en cualquier lenguaje. Si queremos transmitir una letra a la escribimos como "a"; un entero es el mismo número, y los arrays se escriben entre corchetes separados por comas. Los diccionarios así: { 'clave1':'datos1', 'clave2':'dato2', 'numero':100}

El servidor (escrito en PHP, pero podría ser Python, C o cualquier lenguaje) devuelve el código Javascript para hacer un array, o un entero o un string y en el browser el callback que lo recibe hace un eval() del resultado. De eso se trata JSON


Suficiente teoría

Programemos algo.

Para empezar en vez de un script en el servidor vamos a crear una página estática.

archivo: ejemplo1.html

<html>

<script xsrc="prototype.js" type="text/javascript"></script>

<script>

var opt = {

// función a llamar cuando reciba la respuesta

onSuccess: function(t) {

dato = eval(t.responseText);

alert(dato);

}

}

new Ajax.Request('ejemplo1.php', opt);

</script>

<body>

<h1>Prueba de AJAX!</h1>

</body>

</html>

Archivo: ejemplo1.php
"Hola! Soy un mensaje que viajó por AJAX/JSON!"

Para el siguiente ejemplo, un poco mas útil, definimos un DIV para que el usuario haga click sobre el. Cuando hace click se ejecuta un request AJAX. Esta vez la respuesta no es solo un texto sino un array. Cuando llega la respuesta se evalua el array y se lo pasa a otra función que llena un DIV con los datos, agregándoles un poco de texto.


Datos desde PHP


Hasta hora los datos salieron de páginas estáticas. No tiene mucha gracia, asi que vamos a sacar datos deun array de PHP.

Transformar un array en una representación JSON es simple, pero para qué reinventar la rueda. Por eso vamos a usar JSON-PHP. Codificar un array con JSON-PHP es tan simple como esto:

<?php

//Creo en objeto

require_once('JSON.php');

$json = new Services_JSON();

// Armo un array con varios datos

$datos = array(1, 2, 'foo');

$salida = $json->encode($value);

print($salida);

?>

Eso es todo lo necesario. Ahora leamos unos datos desde MySQL para poder hacer aplicaciones mas complejas.

Nota: para crear la tabla MySQL del ejemplo ejecutar:
create database mi_tabla;
create table mi_tabla ( campo1 integer not null, campo2 varchar(50));

archivo: ajax.html

<html>

<script xsrc="prototype.js" type="text/javascript"></script>

<script>

function HicieronClick() {

var opciones = {

// función a llamar cuando reciba la respuesta

onSuccess: function(t) {

datos = eval(t.responseText);

procesar(datos);

}

}

new Ajax.Request('datos2.php', opciones);

}

function procesar(datos) {

// guardo el div donde voy a escribir los datos en una variable

contenedor = document.getElementById("lista");

texto = "";

//Itero sobre los datos que me pasaron como parámetro

for (var i=0; i < datos.length; i++) {

dato = datos[i];

texto += "Dato "+i+" - campo1:"+dato.campo1+" campo2:"+dato.campo2+"
";

}

//Escribo el texto que formé en el div que corresponde

contenedor.innerHTML = texto;

}

</script>

<body>

<h1>Prueba de AJAX!</h1>

<div id="Boton" onClick="HicieronClick()">Hace click sobre este texto para llenar la lista</div>

<div id=lista>

En este div se van a mostrar los datos que se reciben por AJAX.

</div>

</body>

</html>


archivo: datos2.php

<?


//Creo el objeto $json para codificar datos mas adelante

require_once('JSON.php');

$json = new Services_JSON();

$link = mysql_connect('localhost', 'root', '');

mysql_select_db('mi_base');

$query = 'SELECT campo1, campo2 FROM mi_tabla';

$result = mysql_query($query) ;

$datos = array();

//lleno el array $datos con el resultado de la consulta a MySQL:

while ($line = mysql_fetch_array($result, MYSQL_ASSOC)) {

$datos[]=$line;

}

print $json->encode($datos);

mysql_free_result($result);

mysql_close($link);

?>

Lo mas intresante de esto es que no cambiamos en nada la página html y ahora los datos dejaron de ser estáticos y salen de una base de datos. Eso me da pie para la siguiente ventaja:
Separación de código, presentación y diseño gráfico
Primero existió el HTML. Después apareció el PHP y lo fantástico del lenguaje era que a diferencia de CGI (no pregunten cuando empecé a programar...) se podía intercalar programación en medio del HTML.

¿Quien iba a pensar que años después esto iba a ser la principal queja sobre PHP? Ahora todos rogamos por una forma de separar el código de nuestros programas del diseño de las páginas. La forma de programar que presenté en este artículo separa naturalmente el código de la presentación.

Si a los métodos AJAX les sumamos CSS podemos dividir nuestras aplicaciones web de forma prolija.
La lógica de programa y acceso a datos los hacemos en PHP.

La interface de usuario la creamos en HTML definiendo DIVs, botones, etc, pero nada de diseño. Un DIV atrás del otro.

La lógica de presentación en JavaScript (en un archivo .js separado del HTML)

El diseño gráfico (colores, tipografías, etc) en CSS.

Separación de aplicaciones Ajax en capas (PHP, AJAX, HTML y CSS).
Así que lo que comenzó como una mejora en la interface de usuario se transformó, gracias a AJAX, PHP y CSS en una nueva forma de trabajo que espero les ahorre muchos dolores de cabeza. La mayor ventaja que le veo es que la división entre operaciones sobre datos (lo que llaman "logica de negocios"), el código de la interfaz de usuario, y el diseño gráfico están divididos físicamente en archivos separados, y no como una imposición del modelo sino en forma natural.
Que sigue
Como ya se habrán dado cuenta, usamos PHP porque es el lenguaje mas difundido. De la misma forma que reemplazamos el archivo JSON estático por PHP podemos reemplazarlo por cuaquier lenguaje. Nada evita que usemos Python, ASP en un servidor Windows, C o C++ via CGI, Perl, Ruby o el lenguaje que se les ocurra. Lo mejor es que hay librerías para JSON disponibles para muchos lenguajes, y sino escribir una no es nada complicado.

Links recomendados:
www.json.org La página de JSON, con implementaciones en distintos lenguajes.

www.csszengarden.com Excelente site que demuestra lo que se puede hacer usando solo CSS.

prototype.conio.net La página de Prototype

http://wiki.script.aculo.us/scriptaculous/show/Prototype Documentación sobre Prototype
http://thinkcoderepeat.blogspot.com Mi blog ;-)
Mariano Vassallo
mvassallo arroba gmail.com