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

28.8.06

Arquitectura Cliente-Servidor con AJAX y JSON

Programar aplicaciones con AJAX nos permite crear interfaces de usuario (UI) mucho mas rápidas. En esta nota mostraremos como además permite separar en capas los componente de nuestras aplicaciones para que sean mas fáciles de modificar y
mantener.

Hace cinco años una aplicación web era esencialmente un conjunto de páginas HTML con códigos PHP intercalados que a su vez escribían
mas tags HTML. El diseño lo hacíamos con tags como <table>, <font>, <b> y otros. A la hora de hacer modificaciones de diseño, de base de datos o de interface teníamos que modificar una ensalada de códigos donde todo estaba mezclado.

diagrama-de-capas-con-ajax-y-json.jpg
Hoy podemos combinar AJAX, CSS, PHP y Javascript para armar aplicaciones manteniendo el servidor, la interface de usuario y el diseño gráfico como componentes independientes de una aquitectura cliente-servidor, además de crear interfaces
con respuesta mas rápida.
De acuerdo a la forma de programar las aplicaciones AJAX las podemos dividir en dos: clientes livianos y clientes pesados.
Los cliente livianos se llaman asi porque tienen relativamente poco código del lado del cliente. Generalmente una llamada AJAX que al responder ejecuta una función que reemplaza el contenido de un DIV por el texto que devolvió el servidor. Es lo primero que la gente hace para implementar el "look" ajax en un programa. Y es lo mas parecido a seguir generando html desde el lenguaje de servidor (PHP, ASP) pero sin hacer refresh entre páginas.

Los clientes pesados obviamente son lo contrario, tienen mas lógica del lado del cliente. Hoy examinaremos un ejemplo de cliente pesado para mostrar como se puede mantener una
separación en capas en nuestras aplicaciones de forma natural.
La primera separación que haremos será dejar toda la lógica del presentación del lado del cliente. El código PHP (o el lenguaje que usemos en el servidor) tiene que estar libre de tags HTML. Si los datos recibidos deben ser procesados, por ejemplo para formar filas de una tabla, es el cliente quien debe generar el HTML a través de Javascript. Pero para esto es necesario que el código de nuesta interface de
usuario reciba del servidor algo que pueda entender mas allá de cadenas de texto y lo resolveremos utilizando JSON, un nuevo formato de intercambio de datos con muchas ventajas sobre XML.

El código PHP tiene que estar libre de tags HTML


En el servidor solo programaremos web services que realizan acciones o devuelven datos. Será una arquitectura de servicios y no un despachador de páginas.
ejemplo1.png

(ejemplo1.png) La aplicación antes que el usuario haga click para llenar la lista con datos.

ejemplo1.png

(ejemplo2.png) AJAX toma la lista de datos del servidor y escribe los datos dentro de la lista.

¿Que hace el ejemplo?
La aplicación que desarrollamos es un cliente HTML que cuando el usuario hace click sobre un texto pide al servidor los datos de una tabla MySQL. El servidor devuelve un arreglo y el cliente – en Javascript – le da formato y lo escribe en la página. Sin refrescar la pantalla por supuesto.


Capas de la aplicacion

Estructura: HTML
En nuesta aplicación el archivo .html tendrá la función de definir bloques que contendrán datos u otros bloques y eventos que pueden ocurrir el la interface. Los bloques no son mas que DIVs con un nombre para identificarlos. Definiremos una página con un botón (un div que dice “click aquí”) y una lista (otro div) que será rellenada con los datos obtenidos desde el servidor.

<html>
<script src="/javascripts/prototype.js"
type="text/javascript"></script>
<script src="aplicacion.js" type="text/javascript"></script>
<script>
</script>
<body>
<h1>Prueba de AJAX!</h1>
<div id="Boton" onClick="HicieronClick()">Hace click sobre este texto para llenar la lista</div>
<br>
<div id=lista>
En este div se van a mostrar los datos que se reciben por AJAX.
</div>
</body>
</html>


Archivo: ajax.html

Programación de la UI: Javascript

La programación del cliente está contenida íntegramente en uno o mas archivos .js
Aunque como lenguaje Javascript es algo limitado se lo puede ampliar utilizando una librería como Prototype que facilita mucho las cosas. En nuestro ejemplo la llamada AJAX la realizamos con un objeto Ajax.Request , que es parte de Prototype.
Definimos dos funciones: la que es llamada en el evento onClick del DIV “boton” y la que es llamada cuando el servidor contesta el llamado AJAX.

function HicieronClick() {
var opciones = {
//función a llamar cuando reciba la respuesta
onSuccess: function(t) {
datos = eval(t.responseText);

procesar(datos);
}
}
new Ajax.Request('/pruebas/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 numero:"+i+" - campo 1:"+dato.campo1;
texto += " campo2:"+dato.campo2+"<br>";
}
//Escribo el texto que formé en el div que corresponde
contenedor.innerHTML = texto;
}

aplicacion.js

Para lograr una mayor separación entre estructura (HTML) y código podríamos no especificar el evento onClick dentro del código html y en vez asociar el evento desde JavaScript con una función init() y el objeto Event de la librería Prototype. Si esto parece chino, no te preocupes que lo desarrollaré en otro artículo mas adelante.
Sigamos con el ejemplo.
La función HicieronClick(), que se ejecuta porque lo indicamos en el evento onClick del DIV “Boton”, es la que se encarga de hacer la llamada AJAX.
Primero guardamos en la variable opciones los parámetros necesarios. Como es un proceso asincrónico le pasamos una función en línea:

onSuccess: function(t) {
datos = eval(t.responseText);

procesar(datos);
}

Esta función toma los datos recibidos del servidor (t.responseText) los procesa y luego llama a procesar() pasando los datos como parámetro. Mas adelante veremos por
qué usamos la llamada a eval().

La función procesar() obtiene una referencia al DIV “lista” dentro del documento HTML y la guarda para luego escribir los datos ahi. Lo hace llamando a
document.getElementById("lista").
Luego itera sobre el arreglo de datos que recibió y va creando un texto con una línea por cada elemento, concatenando el índice y los dos campos que recibe del
servidor. Además agrega un tag “<br>” después de cada
fila para que al mostrarlo queden uno en cada línea.
Lo que hace es muy simple, pero nos da una idea de como manipular datos recibidos desde el servidor antes de mostrarlos. En vez de solo concatenarlos podríamos crear un DIV por cada fila, asignarles clases en forma condicional, o cualquier otra cosa.
El último paso de procesar es tomar el texto generado en la variable texto y escribirlo en el DIV de destino. Esto se logra con:
contenedor.innerHTML = texto;

JSON
Vamos a volver un segundo sobre la función que recibe los datos del servidor y por qué hace un eval() de lo que recibe.
Como dijimos al principio, los clientes pesados (o ricos, para no ser negativos) en vez de recibir del servidor texto ASCII o HTML y mostrarlo reciben datos y los procesan. Esos datos pueden ser enteros, caracteres, arreglos o de cualquier otro tipo. La pregunta que surge es ¿como devolver desde PHP un arreglo de manera que Javascript lo interprete como tal?
Hasta ahora la solución era codificarlo en XML. De ahí viene la “X” en AJAX. El problema con XML es que no es fácil de leer por un humano, no es facil de codificar y procesar y además tiene mucho overhead.
Como alternativa al uso de XML surgió JSON, que significa Javascript Object Notation. Para codificar en JSON un dato se lo escribe como su representación en código
Javascript. Por ejemplo, para transmitir una cadena se la encierra entre comillas, y un arreglo en JSON se escribe asi: [“primer elemento”, “otro elemento”, 3, 4 , “otros datos” ]

Tiene muchas ventajas. Es simple escribir una rutina que codifique en JSON en cualquier lenguaje, es fácil de leer, es una representación compacta y muy fácil de procesar.
En Javascript es trivial decodificarlo, ya que un mensaje JSON es código Javascript válido. Por eso podemos ejecutar eval(cadena) para obtener el dato correspondiente.
Para codificar o decodificar JSON desde PHP podemos utilizar la librería PHP-JSON o escribir nuestra propia rutina.

Diseño gráfico: CSS
Hasta ahora nuesta aplicación tiene un problema: es horrible. Siguiendo con la filosofía de poner cada cosa en su lugar reservamos todo lo relacionado al diseño
gráfico al archivo CSS correspondiente.
Deberíamos armar el HTML definiendo areas de acuerdo a la función que cumplen, como ser contenedores de otras areas o botones, y defir la clase de cada DIV (el atributo
class=“...” ), pero olvidarnos de tags como <font>, <b> y de usar <table> pasa posicionar elementos en las páginas. No tenemos lugar para hacer un tutorial de CSS aquí, pero hay muchos ejemplos de como posicionar elementos en una página utilizando CSS.
Un recurso interesante en CSS Zen Garden (www.csszengarden.com) donde se muestra como la misma página HTML puede tomar infinidad de apariencias solo cambiando el CSS en uso. El site de ESPN (www.espn.com) también recurre a CSS para realizar un
formato de varias columnas de noticias.
Trabajando de de esta forma nuestra aplicación puede sufrir cambios de diseño gráfico sin tener que tocar los archivos HTML ( ni hablar de los archivos PHP).

Usando un archivo CSS cambiamos la ubicación y colores de los DIVs


screenshot-con-css.png



zen-garden-con-css.png

(Zen Garden: con CSS.png) Ejemplo de diseño
gráfico integral con CSS: CSS Zen Garden


zen-garden-sin-css.png

(Zen Garden: sin CSS.png) Si deshabilitamos CSS vemos que la
página está compuesta exclusivamente por texto


Comunicación con el servidor: JSON
Como dijimos anteriormente para que la aplicación pueda procesar los datos que recibe del servidor necesitamos que los entienda. Si el servidor devolviera datos XML los podríamos procesar desde Javascript. Ese es el espíritu original de AJAX. Pero XML tiene algunos inconvenientes: no es fácil de leer por una persona, no es facil de generar ni de procesar y tiene mucho overhead de transmisión. Para resolver estos problemas se inventó JSON, que significa Javascript Object Notation, aunque no se limita a Javascript. Consiste en codificar los datos como la instrucción que los representa en Javascript. Básicamente si el servidor quiere devolver un string debería escribir “este es un string” (incluyendo las comillas) y si quiere devolver un arreglo
podría transmitir: ["Hola! Soy un elemento!", "Dato número 2",
"ultimo dato"] La utilidad de esta codificación es que es fácil
de leer por humanos, compacta, trivial para codificar y desde Javascript se la decodifica con un simple eval().
Por ejemplo:
miarreglo = eval(respuestadelservidor);

Una de las empresa que adoptó JSON para sus web-services públicos es Yahoo!, que da la opción de utilizar una interface SOAP (XML) o JSON.
En nuestro ejemplo en PHP utilizaremos la librería PHP-JSON para codificar las respuestas.

Otros lenguajes
En este artículo elegimos programar el servidor en PHP, pero al estructurar la aplicación como cliente servidor podemos implementar los web services en cualquier otro lenguaje. Hay muchas librerías para codificar los datos en JSON disponibles.
Implementar una propia también es fácil.

Servidor: PHP
Dejamos la capa del servidor para el final intencionalmente porque es la parte mas simple del sistema.
Como elegimos una arquitectura de servicios el servidor solo tiene que procesar los datos que recibe, realizar alguna tarea y devolver datos codificados en JSON.
La mayor parte del código del ejemplo se ocupa de realizar la consulta a MySQL para obtener los datos.
<?

//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);
?>


datos2.php

¿Que sigue?
El ejemplo que hicimos es muy simple pero sirve para ilustrar la forma de estructurar una aplicación como un cliente programado con HTML y Javascript y un servidor en PHP que proporciona servicios web, y ya no como muchas páginas enlazadas.
El siguiente paso sería programar un servicio web que tome parámetros y agregar mas servicios web al servidor. Una forma de hacerlo es proporcionar una URL distinta para cada
función que quiero llamar desde AJAX, separando así cada web service en un archivo PHP diferente y organizándolos por directorios. Otra forma es crear un único archivo PHP que tome de la variable $_REQUEST el nombre de la función que se quiere llamar.

La elección de PHP para el ejemplo se debe a que es el lenguaje mas difundido para programación web, pero nuestra arquitectura permite reemplazar el servidor por cualquier otro que implemente los mismos web services con JSON. Podríamos haberlo programado sobre ASP .NET, Python, Perl, C (como CGI) o cualquier otro lenguaje y no tendríamos que cambiar nada en el cliente. El modelo también es independiente de la
plataforma elegida.

Código fuente de los ejemplos:
Los ejemplos están en un repositorio SVN en google, pueden verlos con un browser en la dirección: http://ejemplosajax.googlecode.com/svn/trunk/

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