martes, 10 de marzo de 2009

Consumiendo un Servicio Web en PHP desde AJAX, Parte 1: Crear el servicio


Otra solución para múltiples plataformas


Otra forma de que tenemos para acceder a la funcionalidad de nuestro servidor Web es a través de los Servicios Web, cuyo funcionamiento es similar al modo de trabajo que hemos utilizado hasta ahora en el que se solicita una página Web por medio de una petición HTTP, mandándole una serie de parámetros y recibiendo e interpretando la respuesta del servidor. Ahora bien, como la información nos indica los Servicios Web consisten una serie de estándares y protocolos para llevar a cabo el intercambio de datos entre nuestros clientes y el servidor Web, y es gracias a ésto que existe una diferencia entre ambos modos de trabajo, ya que gracias a estos protocolos trabajaremos de manera más transparente al realizar la comunicación entre nuestras aplicaciones, al dejar varios de los detalles de esta labor a la implementación del servicio Web que estemos utilizando. El gran potencial de los servicios Web es que permiten la comunicación de aplicaciones situadas en diferentes plataformas de manera estándar, por lo que podríamos tener un servicio Web hecho en .Net y consumirlo desde un cliente Java, o un servicio Web en PHP y consumirlo desde un cliente .Net, con total independencia del sistema operativo o el manejador de base de datos que estemos utilizando.

En este artículo, me propongo mostrar el ejemplo del uso de un Servicio Web programado en PHP desde nuestro cliente AJAX, realizando las operaciones de consulta, inserción y actualización de los registros de una tabla en nuestra base de datos obras_literarias de MySQL, las cuales serán solicitadas desde nuestro cliente AJAX.

Antes de comenzar

Para desarrollar nuestro servicio Web desde PHP utilizaremos las implementaciones de los protocolos XML-RPC/SOAP que nos ofrece la clase soap_server, la cual esta contenido en la biblioteca del archivo nusoap.php que podemos descargar de manera totalmente gratuita desde el enlace que acabamos de indicar -la documentación completa la encuentran aquí-, en mi caso la última versión disponible que encontré es la 0.7.3. Una vez a nuestra disposición incluiremos el archivo nusoap.php en el directorio de nuestro servidor Web para hacerle referencia en el programa PHP que realizaremos. Además nos apoyaremos en la clase AccesoADatos que definimos en un post anterior.

Nomenclatura utilizada:

-El protocolo de comunicación que se utilizará esSOAP, que es el que define el mecanismo de comunicación entre un cliente (en esta caso en AJAX) y un servicio Web (en este caso en PHP).
-En la definición de este servicio Web también aparecerá el término WSDL siglas de Web Services Description Language, que es un formato XML que se utiliza de manera estándar para describir las características de los servicios Web. Dentro del código definiremos algunas de las características del WSDL del servicio Web que implementaremos.

El trabajo con la base de datos

El sistema manejador de base de datos seguirá siendo MySQL, dentro del cual tendremos la base de datos obras_literarias, en la cual encontramos la tabla autores, que ya habíamos utilizado en los posts anteriores y se puede crear a través del siguiente script:


CREATE TABLE `autores` (
`Id` mediumint(9) NOT NULL,
`Nombre` varchar(60) NOT NULL,
`Nacionalidad` varchar(50) NOT NULL,
`Profesion` varchar(60) NOT NULL,
PRIMARY KEY (`Id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;


Si lo deseamos podemos insertar algunos registros, aunque no es un requisito ya que el sistema que haremos incluirá la inserción de registros:
INSERT INTO `autores` ( `Id` , `Nombre` , `Nacionalidad` , `Profesion` )
VALUES (
'1', 'Juan Rulfo', 'Mexicano', 'Novelista'
),(
'2', 'Pablo Neruda', 'Chileno', 'Poeta'
),(
'3', 'Miguel de Cervantes Saavedra', 'Español', 'Novelista, poeta y dramaturgo'
),(
'4', 'Jorge Luis Borges', 'Argentino', 'Ensayista, escritor y poeta'
);


Trabajo del lado del servidor

Para el servidor crearemos el programa PHP servicio.php, dentro del cual declararemos el servicio Web SOAP que que contendrá los métodos que realizarán las labores de consulta y actualización de la tabla autores.

El código para el trabajo es el siguiente (en seguida explicaré cada uno de los pasos que se fueron realizando):

servicio.php

<?php
require("nusoap.php"); //Referencia al archivo que contiene la clase soap_server
require("AccesoADatos.php");//Referencia al archivo que contiene la clase AccesoADatos
//Implementación del servicio Web
$servicio = new soap_server; //Instancia de la clase para la creación del servicio Web
$servicio->soap_defencoding = "UTF-8"; //Señalamos que el juego de caracteres que utilizaremos es UTF-8
/*
* Definimos un espacio de nombres (namespace) para el servicio Web, funciona como un identificador del servicio Web
* Web -en este caso usamos una URL-
*/
$ns = "http://localhost";
$servicio->configureWSDL('ServicioDeAutores',$ns); //Configuramos el WSDL del servicio Web (Param 1: Nombre del servicio Web, Param 2: Namespace del servicio Web)

/*
*Definimos cuales serán las funciones que poseerá nuestro servicio Web con el metodo register, como primer
* parámetro recibe el nombre de la función, en el segundo y tercer parámetro se incluyen dos arreglos asociativos que especifican los parámetros
* que reciben y los valores devueltos por estas funciones respectivamente
*/
$servicio->register('buscaAutor',
                    array('id'=>'xsd:string'),
                    array('nombre'=>'xsd:string','nacionalidad'=>'xsd:string','profesion'=>'xsd:string','error'=>'xsd:string'),
                    $ns); //Recibirá el id del autor que es de tipo string y devolverá un arreglo con los datos del registro
$servicio->register('actualizaAutor',
                    array('id'=>'xsd:string','nombre'=>'xsd:string','nacionalidad'=>'xsd:string','profesion'=>'xsd:string'),
                    array('mensaje'=>'xsd:string'),
                    $ns); //Recibirá los datos del autor y devolverá un mensaje tipo string
//Obtenemos los parámetros del encabezado HTTP
if(isset($HTTP_RAW_POST_DATA))
{
    $input = $HTTP_RAW_POST_DATA;
}
else
{
    $input = implode("\r\n",file("php://input")); //Secuencia de entrada php://input
}
$servicio->service($input); //Con este método que recibe el contenido del encabezado HTTP se procesa la petición para el servicio Web y se genera la respuesta
exit;

//Funciones para el servicio web
function buscaAutor($id) { //Función para la busqueda de autores
    $acceso = new AccesoADatos('localhost','root','[TuContraseña]','obras_literarias');
    $autor = array('nombre'=>"",'nacionalidad'=>"",'profesion'=>"");
    if($acceso->abreConexion()) { //Accedemos a la base de datos
        $consulta = "SELECT * FROM autores WHERE Id = $id LIMIT 1";
        if($acceso->consulta($consulta)) {//Realizamos la consulta y comprobamos el resultado
            if($acceso->devuelveRegsLeidos() > 0){//Comprobamos si se encontró el registro                                
                $renglon = $acceso->devuelveArreglo();//Extrae el renglon del resultado como un arreglo asosciativo
                $autor['nombre'] = $renglon['Nombre'];
                $autor['nacionalidad'] = $renglon['Nacionalidad'];
                $autor['profesion'] = $renglon['Profesion'];
            }
            else
                $autor['error'] = "Error: No se localizó un autor con el identificador específicado";
        }
        else
            $autor['error'] = "Error de acceso a datos";
    }
    else
        $autor['error'] = "Error de acceso a datos";
    return $autor;
}

function actualizaAutor($id, $nombre, $nacionalidad, $profesion) { //Función para la actualización de la tabla autores
    $acceso = new AccesoADatos('localhost','root','[TuContraseña]','obras_literarias');
    if($acceso->abreConexion()) { //Accedemos a la base de datos     
        $datos = array('Nombre'=>$nombre,'Nacionalidad'=>$nacionalidad,'Profesion'=>$profesion);
        $consulta = "SELECT * FROM autores WHERE Id = $id LIMIT 1";
        if($acceso->consulta($consulta)) { //Realizamos la consulta y comprobamos el resultado
            if($acceso->devuelveRegsLeidos() > 0) { //Comprobamos si se encotró el registro
                $campoLlave = array('Id'=>$id); //Si se encontró, significa que se está actualizando un registro existente                              
                if($acceso->actualizaRegistro("autores",$datos,$campoLlave) > 0)//Realizamos la actualización del registro                            
                    $mensaje = "El registro fué actualizado exitosamente";            
                else
                    $mensaje = "Error: No se registraron cambios en la información del autor";                                        
            }
            else { //En caso contrario se está realizando una insersión
                $datos['Id'] = $id;
                if($acceso->insertaRegistro("autores",$datos) > 0)//Realizamos la inserción del registro
                    $mensaje = "El registro fué insertado exitosamente";            
                else
                    $mensaje = "Error: No se completo la inserción del registro";
            }
        }
        else
            $mensaje = "Error de acceso a datos";            
    }
    else
        $mensaje = "Error de acceso a datos";     
    return $mensaje;
}
?>


Como vemos, al inicio se incluye la referencia a los archivos de las clases que utilizaremos:

require("nusoap.php");
require("AccesoADatos.php");

para implementar el servicio Web y para acceder a la base de datos respectivamente.

En seguida se crea la instancia de la clase soap_server con la cual implementaremos el servicio Web:

$servicio = new soap_server;


Específicamos que el juego de caracteres utilizado es UTF-8:

$servicio->soap_defencoding = "UTF-8";


Por medio de la variable $ns definimos el namespace del servicio Web, que representa el identificador único de nuestro servicio, este caso representado por medio de la URL de nuestro servidor Web local, que indica el directorio en el que podemos localizar el archivo del servicio Web por medio de HTTP:

$ns = "http://localhost";


También podríamos utilizar una URL con dirección IP, o una dirección con un nombre dominio propio servidor si disponemos de una.

En seguida definimos el WSDL del servicio Web, estableciendo el nombre del servicio Web como "ServicioDeAutores" y su namespace como "http://locahost/PruebasPHP":

$servicio->configureWSDL('ServicioDeAutores',$ns);


Una vez hecho esto a través del método registrer() especificamos cuales serán las funciones que ofrecerá ServicioDeAutores:

$servicio->register('buscaAutor',
                    array('id'=>'xsd:string'),
                    array('nombre'=>'xsd:string','nacionalidad'=>'xsd:string','profesion'=>'xsd:string','error'=>'xsd:string'),
                    $ns);
$servicio->register('actualizaAutor',
                    array('id'=>'xsd:string','nombre'=>'xsd:string','nacionalidad'=>'xsd:string','profesion'=>'xsd:string'),
                    array('mensaje'=>'xsd:string'),
                    $ns);

En el primer parámetro de este método definimos el nombre de la función mencionada, en el segundo se definen los parámetros de esta función, el tercer parámetro define los valores que serán devueltos por la función, pudiendo tratarse de un único valor o de un arreglo asociativo, dependiendo del número de valores que se definan. Cómo último parámetro el método register() recibe el namespace del servicio Web. La declaración de estas funciones aparecerá en el bloque final del código del archivo.

En seguida se obtiene el contenido completo del encabezado HTTP que recibe el programa PHP:

if(isset($HTTP_RAW_POST_DATA))
{
    $input = $HTTP_RAW_POST_DATA;
}
else
{
    $input = implode("\r\n",file("php://input"));
}

Este encabezado se puede ser accedido por medio de la variable predifinida $HTTP_RAW_POST_DATA o utilizando la secuencia de entrada php://input.

A continuación y para finalizar con la implementación del servicio Web utilizamos el método service(), el recibe el contenido del encabezado HTTP y procesa la petición para el servicio Web y se genera la respuesta XML:

$servicio->service($input);
exit;


Seguido de la instrucción exit para finalizar el programa PHP.

En el siguiente bloque de código aparece la declaración de las funciones buscaAutor y actualizaAutor, en la primera se lleva a cabo la búsqueda de una autor en la base de datos por medio del $id recibido. La segunda realiza la actualización o inserción de un registro, dependiendo de si el valor campo "Id" proporcionado existe o no en la base de datos.

Nota: Antes de probar el servicio Web recuerden modificar el código anterior agregando la contraseña de acceso a su SMBD MySQL en la parte indicada por [TuContraseña].

Y ahora, gracias a este este código podremos implementar nuestro servicio Web que será consumido por el cliente AJAX que desarrollaremos, con la ventaja de que este mismo servicio puede ser utilizado por cualquier otra aplicación que soporte la utilización de servicios Web.

Para probar que todo anda bien con el ServicioDeAutores podemos acceder a él por medio de nuestro navegador, utilizando la ruta del servidor Web en la que está almacenado, para este ejemplo ésta sería: http://localhost/servicio.php, obteniendo un resultado como el que sigue:



Debido a que nuestro navegador es capas de interpretar el contenido XML de la respuesta del servicio Web, nos ofrece la posibilidad de visualizar su WSDL, así como las características de la funciones que éste posee. El WSDL arrojado en este ejemplo es el siguiente:

img


Mientras que al seleccionar alguna de las funciones nos ofrece una descripción como la que sigue:



Si todo salió bien nuestro servicio Web ya funciona, ahora todo lo que queda es probarlo desde un cliente, cuya programación veremos en el siguiente artículo.

Hasta la próxima.

1 comentarios:

Wilfo dijo...

Quiero retornar 15 elementos de a traves de mi webservice pero no creo que sea lo mismo porque en la consulta pones un limit 1 yo quisiera limit 10.Algun consejo.
logica_razon@hotmail.com

Publicar un comentario