Está en la página 1de 13

Realiza llamadas de servicio Ajax con PHP, jQuery y JSON

Un sistema centralizado y estandarizado basado en eventos


Jeremy J. Wischusen Web Application Architect Binary Neuron L.L.C. Nivel de dificultad: Intermediaria Fecha: 25-09-2012

En este artculo, conozca un sistema para hacer y responder a las llamadas de servicio de Asynchronous JavaScript and XML (Ajax) de una manera coherente, basada en eventos. El sistema puede determinar si una llamada de proceso remoto tiene xito o fracasa. Descubra cmo estandarizar el formato del resultado de los objetos retornados por las llamadas de servicio Ajax, proporcionar respuestas basadas en eventos a las llamadas de Ajax y centralizar el manejo de los resultados de Ajax. El sistema utiliza tecnologas PHP, jQuery y JSON, y un cdigo de ejemplo lo gua a travs de la construccin del sistema. El artculo finaliza con un ejemplo de llamada Ajax que muestra cmo interactan las piezas del sistema.

Introduccin
En este artculo, conozca un sistema para hacer y responder a las llamadas de servicio Ajax de una manera coherente, basada en eventos utilizando PHP, jQuery y JSON. El sistema se destina a llamadas de Ajax para servicios como inicio de sesin y actualizacin de perfil (no para la simple carga de contenido, como una pgina HTML). Usted puede utilizar este sistema para determinar si una llamada de proceso remoto tiene xito o fracasa. Acrnimos de uso frecuente
Ajax: Asynchronous JavaScript + XML DOM: Document Object Model HTML: Hypertext Markup Language JSON: JavaScript Serialized Object Notation Marcas Pagina 1 de 13

Copyright IBM Corporation 2012 Realiza llamadas de servicio Ajax con PHP, jQuery y JSON

developerWorks

ibm.com/developerWorks/ssa/
PHP: Hypertext Preprocessor

Para seguir con este artculo se supone que usted: Est familiarizado con la base de la programacin orientada a objetos en JavaScript y PHP. Est familiarizado con el modelo de eventos DOM Level 2 y en cmo interactuar con ella en JavaScript. Para el sistema de ejemplo, usted interacta con este modelo utilizando la librera jQuery. Tiene un conocimiento bsico de los conceptos de Ajax. Sabe cmo los objetos se construyen y son referidos utilizando la notacin JSON. Consulte Resources para informacin adicional sobre estas tecnologas y conceptos. Tecnologas subyacentes El sistema descrito en este artculo utiliza las siguientes tecnologas: Acceso a un servidor PHP 5 con una funcin json_encode de PHP (requiere PHP 5.2.0 o mayor y PHP Extension Community Library o PECL, JSON 1.2.0 o mayor). La biblioteca jQuery JavaScript (Versin 1.4.4 o mayor).

Objetivos del sistema


El escenario involucra a una empresa que ha decidido rehacer uno de sus sitios web. Como parte del rediseo, la empresa quera que el inicio de sesin y la edicin de perfiles se hiciera con ventanas emergentes Ajax. Debido a que el sitio ya estaba en renovacin, se aprovech la oportunidad para implementar ideas para estandarizar la manera de hacer y responder las llamadas de servicio Ajax. El nuevo sistema fue creado para lograr tres objetivos principales: Estandarizar el formato del resultado de los objetos retornados por las llamadas de servicio Ajax. Proporcionar respuestas basadas en eventos a las llamadas de Ajax. Centralizar el manejo de resultados de Ajax. El resto de este artculo describe cmo el sistema alcanza estos objetivos.

Estandarizar el formato del resultado de los objetos retornados por las llamadas de Ajax.
La clase PHP ServiceResult estandariza el objeto resultante creado al hacer una llamada de Ajax. Todas las llamadas de servicio Ajax retornan un objeto codificado
Realiza llamadas de servicio Ajax con PHP, jQuery y JSON Pagina 2 de 13

ibm.com/developerWorks/ssa/

developerWorks

en JSON de este tipo, dando a todas las llamadas de servicio Ajax una interfaz coherente y predecible. El Listado 1 muestra la clase PHP ServiceResult . Listado 1. Clase PHP ServiceResult .
<?php class ServiceResult { /** * * @var Boolean */ public $success; /** * * @var Array */ public $errors; /** * * @var Array */ public $messages; /** * Holds data returned by a service or passthrough data. */ public $data; /** * * @var String - Event name triggered in JavaScript when service call successful. */ public $onSuccessEvent; /** * * @var String - Event name triggered in JavaScript when service call fails. */ public $onErrorEvent; } ?>

En la parte superior de la clase, el listado define: La propiedad success , que indica si el proceso que se invoca tiene xito o fracasa. Esto no es una indicacin de si la llamada de Ajax en s tiene xito. Si la llamada de Ajax falla, no obtendr el objeto JSON por lo que an necesita manejar las fallas de Ajax con un manejador de fallas de algn tipo. En el ejemplo, xito indica si el usuario es encontrado durante el proceso de inicio de sesin, o si el perfil del usuario se actualiza correctamente. El array errors , que contiene toda la informacin acerca de por qu la llamada no tiene xito. Por ejemplo, si un proceso de inicio de sesin falla, puede contener un mensaje como "No user with that user name and password failed." Al permitir que el objeto ServiceResult pase de nuevo mensajes de error, usted no tiene que modificar el cdigo de los mensajes en su cdigo JavaScript. El cdigo JavaScript simplemente necesita saber que los mensajes de error destinados al usuario estn contenidos en este array. La propiedad messages , que tambin es un array, vuelve a pasar mensajes sin error relacionados al manejador de resultados. Los mensajes pueden ser lo que
Realiza llamadas de servicio Ajax con PHP, jQuery y JSON Pagina 3 de 13

developerWorks

ibm.com/developerWorks/ssa/

usted quiera que el usuario sepa relacionado a la llamada de servicio. Usted puede incluir mensajes de xito, como "You have been logged in." Al mantener separados errores y mensajes genricos, usted no tiene que determinar si un mensaje se relaciona con un error o si es meramente informativo cuando el manejador de resultados se lo muestra al usuario (as se simplifica la lgica en el lado del cliente). La propiedad data que proporciona un mtodo de pasar datos arbitrarios de vuelta al manejador de resultados. Por ejemplo, si est llamando a un servicio de inicio de sesin, data puede contener datos de perfil de usuario. Mientras la propiedad data en s es genrica, los manejadores de resultados para la solicitud especfica deben hacer suposiciones acerca de los datos contenidos en esta propiedad basndose en la llamada de servicio realizada. En cualquier caso, la propiedad data permite a todos los manejadores de resultados saber dnde buscar esos datos. Las propiedades onSuccessEvent y onErrorEvent son cadenas de caracteres para definir el evento a ser transmitido para una llamada de servicio exitosa o fallida. Otra vez, esto se refiere al proceso y no a la llamada de Ajax en s. Ejemplos de dichos eventos son userLoggedIn para xito o loginFailed para falla.

Proporcionar respuestas basadas en eventos a las llamadas de Ajax


El segundo objetivo del sistema es dar respuestas a las llamadas de Ajax basadas en eventos utilizando el modelo de eventos DOM Level 2. Para lograr esto, el ejemplo utiliza uno de los diseos orientados a objetos en JavaScript. Para que el sistema funcione, los objetos individuales deben ser capaces de suscribirse a los eventos DOM Level 2 que son retornados por la llamada de servicio (eventosonSuccessEvent y onErrorEvent pasados de nuevo por el objeto PHP ServiceResult ). Todos los objetos deben suscribirse al mismo objeto que distribuye el evento. Crear una cadena bsica de herencia de objetos para su objeto JavaScript. Crear la cadena de modo que si alguna vez necesita cambiar la biblioteca de JavaScript subyacente, puede hacerlo sin perturbar la interfaz para interactuar con el modelo de eventos DOM Level 2 en sus objetos JavaScript. El objeto EventDispatcher est en el nivel superior de la cadena de herencia, como se muestra en el Listado 2, y es responsable por la definicin de la interfaz JavaScript para interactuar con el modelo de eventos DOM Level 2. Tambin es responsable de asegurar que todos los objetos JavaScript se suscriben al mismo distribuidor.

Realiza llamadas de servicio Ajax con PHP, jQuery y JSON

Pagina 4 de 13

ibm.com/developerWorks/ssa/

developerWorks

Listado 2. Objeto EventDispatcher


function EventDispatcher() { } EventDispatcher.prototype.addListener = function (eventName, listener) { this.dispatcher.bind(eventName, listener) } EventDispatcher.prototype.removeListener = function (eventName, listener) { this.dispatcher.unbind(eventName, listener) } EventDispatcher.prototype.dispatch = function (eventName, data) { this.dispatcher.trigger(eventName, data); } EventDispatcher.prototype.dispatcher = jQuery(document);

En el Listado 2: Las funciones addListener y removeListener permiten que usted aada y elimine oyentes desde el objeto de distribucin. El parmetro eventName es el evento al que se est suscrito. El parmetro listener es la funcin a ser registrada. La funcin dispatch transmite el evento especificado en el parmetro eventName . El parmetro data proporciona un mtodo de hacer pasar datos para cualquier funcin de oyente suscrita. La propiedad dispatcher se configura para un objeto jQuery que hace referencia al objeto DOM de documento. Al configurar la propiedad dispatcher para un objeto jQuery haciendo referencia al objeto DOM de documento, todos los eventos de objeto son registrados y transmitidos por el objeto DOM de documento que existe en una pgina dada. Esto es simplemente una propiedad del objeto EventDispatcher , y todos los mtodos hacen referencia a esa propiedad de distribucin. Usted puede cambiar la distribucin subyacente al cambiar esa propiedad. Usted puede utilizar cualquier objeto que proporcione acceso al modelo de eventos DOM Level 2 por el simple cambio de los mtodos de distribucin y actualizacin para corresponder a esa interfaz de distribucin (sin interrumpir cualquiera de los objetos que se heredan del objeto EventDispatcher ). Es clave que todos los objetos se suscriban al mismo distribuidor. El paso siguiente es permitir scripts individuales para heredar las funciones definidas por el objeto EventDispatcher . La empresa en este escenario tiene una convencin para que cada pgina en el sitio tenga un nico objeto controlador responsable por la funcin de esa pgina. Para cerrar la brecha entre estos controladores individuales de pgina y el objeto EventDispatcher , cree una clase BaseController que herede desde el objeto EventDispatcher .

Realiza llamadas de servicio Ajax con PHP, jQuery y JSON

Pagina 5 de 13

developerWorks

ibm.com/developerWorks/ssa/

Por brevedad, las funciones no especficamente relacionadas a la distribucin de eventos se omiten de la muestra de cdigo. Existen otras cosas que los controladores heredan de esta clase. El Listado 3 muestra la clase BaseController . Listado 3. Clase BaseController
function BaseController() { } BaseController.prototype = new EventDispatcher();

Debido a que la propiedad de prototipo BaseController se configura para un objeto EventDispatcher , cualquier controlador especfico de pgina que se hereda de BaseController incluye funciones de distribuidor de eventos.

Centralizar el manejo de resultados de Ajax


La meta final del sistema es centralizar el procesamiento de los resultados de las llamadas de servicio Ajax. Usted puede hacerlo utilizando la funcin ajaxComplete de jQuery, que se llama automticamente cada vez que una llamada de Ajax se completa utilizando jQuery. Para garantizar que esto ocurre, coloque el cdigo del listado 4 en un archivo script que usted incluye en cualquier pgina que haga llamadas de servicio Ajax. Listado 4. Funcin ajaxComplete de jQuery
jQuery(document).ajaxComplete(function(event, request, settings) { if (settings.dataType == 'json') { var dispatcher = new EventDispatcher(); var result = jQuery.parseJSON(request.responseText); if (result) { if (result.success == true && result.onSuccessEvent) { dispatcher.dispatch(result.onSuccessEvent, result) } else if (result.onErrorEvent) { dispatcher.dispatch(result.onErrorEvent, result) } } } })

El manejador se registra contra el objeto del documento porque usted sabe que todas las pginas tienen este objeto. Cada vez que se invoca la funcin, se pasa: Un objeto event de jQuery Ajax (el parmetro evento). El XMLHttpRequest (el parmetro request ). Un objeto representando las configuraciones utilizadas para hacer la llamada de Ajax original (el parmetro settings ). Para el sistema de ejemplo, usted solo est interesado en el objeto XMLHttpRequest y el objeto settings . Observe ms de cerca el cdigo dentro del manejador en el Listado 4. El manejador verifica primero el objeto settings para ver si el formato del resultado est
Realiza llamadas de servicio Ajax con PHP, jQuery y JSON Pagina 6 de 13

ibm.com/developerWorks/ssa/

developerWorks

configurado para JSON. (Recuerde que el propsito de este sistema no es responder a solicitudes simples de carga de contenidos, sino que responder a llamadas de Ajax basadas en servicio, que retorna, codificado en JSON, un ServiceResult ). Si el tipo de datos retornados por la solicitud de Ajax no es JSON, usted no est interesado en responderla y el manejador omite todo el cdigo restante. Si el tipo de datos es JSON, el cdigo crea una instancia JavaScript de EventDispatcher. Debido a que todas las instancias de la clase EventDispatcher hacen referencia a la misma instancia de distribuidor, los eventos transmitidos por ella desencadenan todos los oyentes registrados en ella por cualquier objeto JavaScript que extiende la clase EventDispatcher . El cdigo entonces toma una referencia codificada en JSON de la propiedad responseText del objeto de la solicitud (usando la funcin de jQuery parseJSON ), y la almacena en la variable result . Suponiendo que el anlisis de responseText se realiza correctamente, el manejador comprueba si el objeto result indica que el procedimiento es exitoso comprobando la propiedad success . Si se realiza correctamente, el manejador comprueba si existe definido un onSuccessEvent . Si existe, la instancia de distribuidor event retransmite ese evento junto con el objeto result . Si el objeto de resultado no indica que el proceso es exitoso, el cdigo comprueba si existe un onErrorEvent. Si est definido, la instancia dispatcher retransmite el evento, pasando de nuevo por el objeto result . Mediante las funciones ajaxComplete de jQuery, usted ahora puede notificar a su cdigo del lado del cliente para reaccionar basado en eventos. Los objetos del lado del cliente no tienen que registrarse como oyentes en la llamada de Ajax. El cdigo del lado del cliente no tiene siquiera que saber que se est realizando una llamada de servicio. Simplemente tiene que saber qu eventos escuchar y cmo responder a los datos que pasan de nuevo por l.

Ejemplo de llamada Ajax


En esta seccin, una simple llamada de servicio de inicio de sesin de Ajax muestra cmo las piezas del sistema interactan. Por simplicidad, se supone que usted ha incluido correctamente todos los archivos necesarios de PHP y JavaScript. Cree un archivo PHP que represente el servicio invocado y retorne, codificado en JSON, un objeto ServiceResult . El Listado 5 muestra un ejemplo.

Realiza llamadas de servicio Ajax con PHP, jQuery y JSON

Pagina 7 de 13

developerWorks Listado 5. Archivo PHP

ibm.com/developerWorks/ssa/

<?php $ctrl = new LoginController(); $result = new ServiceResult(); $result->success = $ctrl->login($_POST['username'], $_POST['password']); $result->errors = $ctrl->errors; $result->onSuccessEvent = 'refreshPage'; $result->onErrorEvent = 'userLoginFailed'; echo json_encode($result); ?>

Es necesario un objeto JavaScript que invoque el servicio. Para este ejemplo, se supone que usted ya cre un formulario HTML de inicio de sesin. Llame el objeto responsable por hacer la llamada de servicio LoginController, como en el Listado 6. Llamada de servicio Listado 6. LoginController
LoginController.prototype.login = function() { var self = this; var username = jQuery('#loginForm .email').val() var password = jQuery('#loginForm .password').val() var data = { username:username, password:password, }; jQuery.ajax({ url:'login.php', async:true, service:'login', type:'post', dataType:'json', data:data }); function LoginController() { var self = this; jQuery(document).ready(function() { self.onLoad(); }) } LoginController.prototype = new BaseController(); LoginController.prototype.onLoad = function() { var self = this; this.addListener('userLoginFailed', function(event, result) { self.onLoginFailed(result); }) } LoginController.prototype.onLoginFailed = function(result) { jQuery('#errorDisplay').html(result.errors[0]); } }

Debido a que este sistema responde a las llamadas de servicio Ajax mediante eventos, usted no pasa manejadores de resultados y fallas a la llamada jQuery.ajax . Ahora que ha invocado el servicio, usted desea permitir a los objetos responder a onSucessEvents y onErrorEvents definidos el el objeto ServiceResult que
Realiza llamadas de servicio Ajax con PHP, jQuery y JSON Pagina 8 de 13

ibm.com/developerWorks/ssa/

developerWorks

es retornado por el servicio de inicio de sesin. Es necesario que los objetos que responden hereden desde EventDispatcher, que es heredable extendiendo BaseController. En este caso, el objeto LoginController muestra al usuario un mensaje explicando que el intento de inicio de sesin ha fallado. Si el inicio de sesin tiene xito, el objeto AppController responde actualizando la pgina. Empiece con el LoginController, como en el Listado 7. Aadiendo oyentes de Listado 7. LoginController
function LoginController() { var self = this; jQuery(document).ready(function() { self.onLoad(); }) } LoginController.prototype = new BaseController(); LoginController.prototype.onLoad = function() { var self = this; this.addListener('userLoginFailed', function(event, result) { self.onLoginFailed(result); }) } LoginController.prototype.onLoginFailed = function(result) { jQuery('#errorDisplay').html(result.errors[0]); }

El constructor invoca una funcin onLoad . Esto no es clave para el ejemplo, pero se incluye porque puede ser necesario que este controlador haga referencia a objetos DOM no disponibles hasta que se cargue la pgina. Dos elementos claves a notar son: El objeto prototipo del LoginController es un BaseController. Por lo tanto, tambin hereda los mtodos de EventDispatcher . Utilice el mtodo EventDispatcher addListener en la funcin onLoad . El evento que se pasa coincide con el onSuccessEvent retornado por el objeto ServiceResult que es retornado por el servicio de inicio de sesin. La funcin de manejador registrada se pasa junto al objeto result , que es el objeto ServiceResult codificado en JSON, retornado por el servicio de inicio de sesin. El mtodo onLoginFailed utiliza el array de error del objeto result para mostrar un mensaje al usuario. El manejo de un inicio de sesin fallido es atendido. Cuando el inicio de sesin del usuario es exitosa, usted desea que la pgina se actualice para que los datos de inicio de sesin del usuario sean actualizados. Sin embargo, hay otras ocasiones en que puede querer responder a llamadas de servicio al actualizar la pgina, por ejemplo, cuando los usuarios actualicen sus perfiles. En vez de tener varios controladores con manejadores de resultados que actualizan la pgina, mantenga esta funcin en un controlador de nivel superior.
Realiza llamadas de servicio Ajax con PHP, jQuery y JSON Pagina 9 de 13

developerWorks

ibm.com/developerWorks/ssa/

Entonces, las llamadas de servicio que quieran actualizar la pgina para actualizar los datos de la sesin pueden hacerlo simplemente distribuyendo el tipo de evento refreshPage como el onSucessEvent. Para hacerlo, repita el proceso que utiliz para el LoginController en el AppController, como en el Listado 8. Objeto Listado 8. AppController
function AppController() { var self = this; jQuery(document).ready(function() { self.onLoad(); }) } AppController.prototype = new BaseController(); AppController.prototype.onLoad = function () { this.addListener('refreshPage', function(event, user) { window.location.reload() }) }

Otra vez, el AppController simplemente configura su prototipo a una instancia de BaseController y registra una funcin de oyente utilizando addListener para el evento refreshPage . Ahora que ha creado los objetos que responden y registrado los oyentes de eventos, incluya el script con la funcin onAjaxComplete de manejador de eventos. Al completarse la llamada de servicio, el manejador onAjaxComplete distribuye el evento apropiado que notifica a la funcin de manejador registrada. No es necesario que el LoginController y el AppController tengan conocimiento uno del otro. Incluso no saben que estn respondiendo a una llamada de servicio --y mucho menos a la misma llamada de servicio.

Resumen
En este artculo se examin un sistema para hacer llamadas de servicio Ajax que: Estandariza el formato del resultado de los objetos retornados por las llamadas de servicio Ajax utilizando un objeto ServiceResult PHP que es retornado en un formato codificado en JSON. Proporciona respuestas basadas en eventos a las llamadas de Ajax diseando un objeto EventDispatcher de JavaScript que permite a todas las subclases registrar y responder a eventos en un distribuidor comn. Centraliza el manejo de los resultados de Ajax mediante un manejador onAjaxComplete de jQuery para actuar como un manejador centralizado que transmite los eventos especificados en el objeto ServiceResult retornado por la llamada de servicio.

Realiza llamadas de servicio Ajax con PHP, jQuery y JSON

Pagina 10 de 13

ibm.com/developerWorks/ssa/

developerWorks

Un ejemplo de llamada Ajax mostr cmo usted puede crear dos objetos JavaScript, que no tienen conocimiento uno de otro, para responder a la misma llamada de servicio.

Realiza llamadas de servicio Ajax con PHP, jQuery y JSON

Pagina 11 de 13

developerWorks

ibm.com/developerWorks/ssa/

Recursos
Aprender Classes and Objects: Lea ms sobre programacin orientada a objetos en el manual de PHP. "Get started with object-oriented JavaScript code" (developerWorks, abril de 2011): Aprenda cmo crear objetos utilizando JavaScript. jQuery Documentation: Aprenda ms sobre la utilizacin de la biblioteca de jQuery. jQuery ajaxComplete function: Obtenga ms detalles acerca de cmo trabaja esta funcin. JavaScript Object Notation: Aprenda ms sobre sintaxis y uso. json_encode: Lea cmo PHP codifica objetos en formato JSON. DOM events: Lea esta entrada de Wikipedia para saber ms acerca de eventos DOM Level 2. developerWorks technical events and webcasts: Mantngase actualizado con la tecnologa en estas sesiones. developerWorks on Twitter: nase hoy para seguir los tweets de developerWorks. developerWorks podcasts: Escuche interesantes entrevistas y discusiones para desarrolladores de software. Demostraciones on demand de developerWorks: Observe demostraciones que van desde la instalacin de productos y configuracin para principiantes hasta funcionalidades avanzadas para desarrolladores experimentados. Obtener los productos y tecnologas jQuery JavaScript library: Descargue la versin 1.4.4 o mayor. IBM product evaluation versions: Descargue o vaya a explore the online trials in the IBM SOA Sandbox y experimente con herramientas de desarrollo de aplicaciones y productos middleware de DB2, Lotus, Rational, Tivoli, y WebSphere. Comentar developerWorks profile: Cree hoy su perfil y vaya a set up a watchlist. XML zone discussion forums: Participe en cualquiera de las diferentes discusiones relacionadas con XML. El developerWorks community: Conctese con otros usuarios developerWorks mientras explora los blogs, foros, grupos y wikis dirigidos a desarrolladores.

Realiza llamadas de servicio Ajax con PHP, jQuery y JSON

Pagina 12 de 13

ibm.com/developerWorks/ssa/

developerWorks

Sobre el autor
Jeremy J. Wischusen Jeremy Wischusen tiene ms de 13 aos de experiencia diseando sitios web y aplicaciones para clientes como Purple Communications, myYearbook.com, HBO y otros, desarrollando sistemas frontend y backend con Flash, Flex, jQuery, PHP, MySQL, MSSQL y PostgreSQL. Ha enseado diseo web, Flash y ActionScript para clientes como Wyeth Pharmaceuticals, The Vanguard Group, Bucks County Community College y The University of the Arts. Copyright IBM Corporation 2012 (www.ibm.com/legal/copytrade.shtml) Marcas (www.ibm.com/developerworks/ssa/ibm/trademarks/)

Realiza llamadas de servicio Ajax con PHP, jQuery y JSON

Pagina 13 de 13

También podría gustarte