SOAP – Server y Cliente en PHP con Nusoap.

Introducción

Antes que nada no voy a entrar en detalles del protocolo sino de como implementarlo con php, pero me consta que lo correcto es al menos aclarar, aunque sea repetitivo, que significan estas siglas.
Sin meterme mucho en el tema puedo contarles que SOAP son las siglas de siglas de Simple Object Access Protocol, el cual obviamente es un protocolo que fue creado por varios grosos (MS, IBM, Etc), y su fuente de datos es el XML con un diseño que cumple el patrón Cabecera-Desarrollo y que actualmente está auspiciado por la W3C.

Es un protocolo que se usa mucho para webservices, y por lo tanto, para hacer una petición desde un cliente se necesita una respuesta desde un servidor.

Si lo que se desea es crear un cliente, el cual hace peticiones a un SOAP servidor que no es nuestro, la tarea será más simple. Ahora, si lo que se desea es tener un cliente, ya el enfoque es otro aunque nada complicado, ya lo verán.

Lo único a tener en cuenta es que debemos contar con una directiva del php.ini indispensable para su funcionamiento, ésta es la directiva always_populate_raw_post_data la cual debe estar en ON.

Otra necesidad es poder tener algo con cual poder escribir y parsear este xml, para ellos tenemos dos opciones: una es usar las funciones que nos da php al habilitar una dll, para más información de esto pueden ver la documentación de php en php.net/soap; dos, usar nusoap, una clase hecha para esta tarea, la cual permite crear cliente, servidor.

Para ser más prácticos les mostraré un simple ejemplo de un servidor y un cliente.

Primer paso, tener nuestro servidor.

Para comenzar no podremos avanzar sin antes tener nuestra querida librería nusoap. En este ejemplo he usado la versión 0.7.2, la cual pueden descargar desde acá.

Una vez en sus máquinas, pueden descomprimir el directorio lib del zip en un directorio nuestro llamado “include” (o el nombre que más les guste). No es necesario mover los ejemplos, pero si gustan pueden darle una mirada, cosa que nunca está de más.

Para usar esta clase todo lo que debemos hacer en nuestro php es incluirla. Entonces, creamos un php que se llame server.php, y en él escribimos:

<?
require_once(‘includes/nusoap.php’);
?>

Ahora bien, necesitamos crear un objeto del tipo servidor, eso es simple, lo hacemos instanciando el método soap_server, nos quedaría algo así:

<?
require_once(‘includes/nusoap.php’);
$server = new soap_server;
?>

Bien, hasta acá venimos bárbaro, pero me olvide de comentarles que la tarea de un servidor es la de servir. Claro que este comentario es obvio!, pero para el caso no se preguntan que es lo que servirá mi servidor? Pues no más que datos es la respuesta que pensarán y es correcta. El tema es nuestros datos se servirán en base a una petición del cliente mediante funciones, tal cual cuando usamos funciones nuestras del tipo getUser( $id ).

Entonces, para procesar de manera simple una petición haremos una función en php, una simple función, por ejemplo:

function hola( $name ){
return “Hola {$name}”;
}

De más esta decir que puedo tener todas las funciones necesarias y estas estar en un archivo aparte, pero para el ejemplo es lo mismo.

Ahora bien, aquí viene lo interesante del servidor y es que registraremos en nuestro SOAP la función que acabamos de crear de la siguiente manera:

$server->register( ‘hola’ );

Solo nos resta tomar toda la petición del cliente, y esto lo haremos con la variable de php llamada $HTTP_RAW_POST_DATA la cual contiene el post en bruto. En caso de no contar con la directiva always_populate_raw_post_data en ON como dijimos, pueden intentar setearla de la siguiente manera, aunque no garantizo su funcionamiento ya que depende de otras configuaraciones del servidor web y OS:

$rawPost = strcasecmp($_SERVER['REQUEST_METHOD'], ‘POST’) == 0? (isset($GLOBALS['HTTP_RAW_POST_DATA'])? $GLOBALS['HTTP_RAW_POST_DATA'] : file_get_contents(“php://input”)) : NULL;

Una cosa que no esta de más es validar el dato que nos manda el cliente, para esto podemos modificar la función para crear un fault, quedando así:

function hola( $name ){
return empty( $name ) ? new soap_fault(‘Client’,”,’Ingrese un nombre válido’) : “Hola ” . $name;
}

Ahora, como está todo en partes, para sintetizar quedaría así nuestro achivo que llamaremos para el ejemplo servidor.php:

<?
$rawPost = strcasecmp($_SERVER['REQUEST_METHOD'], ‘POST’) == 0? (isset($GLOBALS['HTTP_RAW_POST_DATA'])? $GLOBALS['HTTP_RAW_POST_DATA'] : file_get_contents(“php://input”)) : NULL;
require_once(‘includes/nusoap.php’);
$server = new soap_server;
$server->register(“hola”);
$server->service($rawPost);
function hola( $name ){
return empty( $name ) ? new soap_fault(‘Client’,”,’Ingrese un nombre válido’) : “Hola ” . $name;
}
?>

Solo resta nuestro cliente para poder probarlo, que como les decía es mucho más simple.
El mismo todo lo que debe hacer es llamar a nuestro servidor haciendo llamada a la función hola y pasarle un parámetro que es lo que ésta espera.

Para ellos creamos cliente.php, incluimos nuevamente la clase nusoap, e instanciamos al método soapclient pasándole como parámetro la url de nuestro servidor. Una vez creado el objeto haremos un método call a nuestra función hola y le pasaremos los parámetros necesarios, tan simple como esto:

<?
require_once(‘includes/nusoap.php’);
$soapclient = new soapclient(‘http://estudiowas.com.ar/nusoaptest/server.php’);
echo $soapclient->call( ‘hola’ , array(‘name’ => ‘Mundo’) );
?>

Ya tenemos nuestro servidor y nuestro cliente, pueden verlo funcionando desde acá

Con el servidor podemos servir o procesar peticiones de un cliente cualquiera. Con nuestro cliente podemos llamar a un servidor y usar sus prestaciones.

Espero que este ejemplo les sea practico y puedan usarlo en grandes ideas!, acá dejo las descargas:

Nusoap 0.7.2

Ejemplo completo

Llamada al cliente

27 comentarios para “SOAP – Server y Cliente en PHP con Nusoap.”

  1. Claudio Dice:

    Me gusto la simplicidad del todo, y lo mejor es que funciona, no se como es que tengo la directiva esa funcionando, pero lo voy a llamar suerte.

    Ahora tendré que ver como autentificarme contra el servidor y que este me procese el pedido, pero supongo que teniendo esto en mis manos ya podré lograrlo más fácil. Si saben si lo hago como si fueran simples funciones como hola les agradecere a quién aporte ;)

    Gracias campeón.

  2. Helena Dice:

    El ejemplo esta muy bien pero, podrías hacer un ejemplo de un servicio web que cogiera los datos de varias bases de datos distintas y los mostrara en el cliente???

  3. Nicolaspar Dice:

    Helena, lo que pides es simple, deberías en el servidor tener varias conexiones (una por cada diferente base de datos), y luego funciones registradas que hagan lo que necesitas con cada conexión, de manera independiente o combinada.

    De esta manera, el cliente pedirá la llamada a la función del servidor quien le dará los datos necesarios de estas dbs.

    Saludos.

  4. Helena Dice:

    Gracias, Nicolas.

  5. lucas Dice:

    a mi no me funciono!! extraje los archivos y me sale este mensaje cuando compilo el server.php:

    Fatal error: Cannot redeclare class soapclient in C:\Dokumente und Einstellungen\laguero\Desktop\Lucas\nusoaptest\includes\nusoap.php on line 7240

    que paso?

  6. Nicolaspar Dice:

    Lucas: tenés instalada la dll de soap en tu php; más info: http://ar2.php.net/manual/es/ref.soap.php

    No se porque usan el mismo nombre, pero podés editar tu php.ini y así desinstalar esta dll, o bien usar ésta y no nusoap.

  7. cript Dice:

    Está bien la introducción, pero nusoap no permite manejo de sesiones verdad ?¿?

    Imaginémonoes que queremos hacer un webservice, en el que el primer paso sea la autentificación y si estamos autentificados ya podemos acceder a los recursos del webservice de los que obtendremos diferentes resultados dependiendo del usuario que acceda.

    ¿Cómo podríamos hacer esto?

  8. Alvaro Cabrera Dice:

    genial!

    ahora, si sabre como empezar :D

  9. Sabigual Dice:

    Gracias por la publicación, pero me dá este error tu ejemplo y ya tengo la librería activa en mi servidor.

    Fatal error: Cannot redeclare class soapclient in C:\AppServ\www\nusoaptest\includes\nusoap.php on line 7240

    Alguna idea??

  10. Sabigual Dice:

    No creo que sea problema de la librería que trae PHP Version 5.2.3, ya que esta libreria le funciona a otros servidores, ha de ser algo mas, no se, yo uso el proyecto appserver que trae apache, php, mysql y este funciona bien.

    Espero si es posible arrojen mas luz al respecto de este error que no encuentro la razon por la que ni este ni ningun otro ejemplo se me ejecuta en mi servidor.

    Gracias anticipadas por la colaboración muchach@s.

  11. Yulimar Dice:

    Hola. Necesito de su ayuda por favor, si alguien sabe como enviar datos estructurados a un Webservices, escribanme. La estructura es de la siguiente forma:

    string
    string
    string
    char

    string

    Gracias.

  12. elo950 Dice:

    Gracias, me ha sido de mucha ayuda aunque hubiera sido mas completo si usabamos un wsdl, aun asi es el yuyorial mas simple que encontre y me sirve de base, gracias de nuevo

  13. German Dice:

    Gracias por el aporte y no te molestes por los patudos que piden ayuda para sus trabajos.
    Saludos

  14. Luis Dice:

    Estimados.

    Tengo un problema me conecto a un web service que esta en .net. instalado en la red local. Al invocar al metodo desde el Cliente y pasarle un parametro , funciona a la perfeccion.

    Pero si hago lo mismo a un web service que esta en la internet , no llegan los parametros que envio.

    Ocupo:
    - nusoap nusoap-0.7.3.zip
    - PHP Version 5.0.5

    y asi hago el llamado al webservice llamando al metodo ValidaXML y pasando como parametro hola:

    require_once(‘lib/nusoap.php’);
    $wsdlURL = ‘http://test.dvs.cl/WebServiceLuisRelease/WebServiceLuis.asmx?WSDL’;
    $soap = new soapclient($wsdlURL, ‘WSDL’);
    $result = $soap->call(‘ValidaXML’,'hola’);
    $data=$result["ValidaXMLResult"];

    Tendre que configurar el php.ini o algo asi , ya que tengo comunicacion con el web service que esta en internet , pero no llegan los parametros.

  15. Sonao Dice:

    Buenas, estoy intentando comunicarme con un servicio web por soap. Tengo la siguiente duda: ¿las funciones del servidor las creo yo o las crean ellos para que las llamen desde fuera?

  16. nicolaspar Dice:

    Por si no quedo claro, el cliente y el server no son más que archivos PHPs en nuestro ejemplo. Entonces, si tenés acceso al ws server, o sos el que lo crea deberás si crear las funciones.
    Sino, solo podrás usar las que te hayan creado en el mismo usando solamente el ws cliente.

  17. Antonio Dice:

    hola, estoy empezando a usar un servicio nusoap como cliente y éste me responde en xml, mi pregunta es ¿como puedo coger los datos de ese xml? yo se como coger los datos de un archivo en xml pero no en una respuesta de nusoap, estoy buscando por internet y no encuentro nada, espero que me puedas ayudar, gracias de antemano. Saludos

  18. Matony Dice:

    El articulo esta muy bien explicado lo malo es que no puedo ver en funcionamineto el ejemplo.

    Descargue los archivos y tampoco lo puedo ver. Me sale este mensaje a alguien mas le salio esto?? como lo soluciono??

    Fatal error: Cannot redeclare class soapclient in C:\xammp\htdocs\webservice\nusoaptest\includes\nusoap.php on line 7240

  19. Enrique Dice:

    A mí me sucede lo mismo que Matony, me sale el mismo error tanto para el ejemplo que en mi máquina..

    ¿Alguien sabrá por qué ocurre ésto?

  20. nicolaspar Dice:

    Hola, ese error es porque tenés habilitada la extensión soap de PHP y la class nusoap usa los mismos nombres. Leete como usarla en http://www.php.net/soap o bien edita el php.ini y pon en OFF esta extensión. Saludos.

  21. isantos Dice:

    que tal..
    gracias por el aporte, es un ejemplo muy sencillo y facil de hacer, ya lo eh checado… solo que necesito que me ayudes a recoger datos de una bd mysql, eh estado intentandolo pero aun no puedo hacerlo….
    Te invito a que visites y comentes mi blog | http://www.ddsmedia.net/blog

  22. atmjesus Dice:

    Hola!!

    Yo lo he probado pero en vez de devolverme por pantalla “Hola Mundo”, me devuelve “Array” :S

    ¿Alguna solución?

    Graciass

  23. GUiLTY Dice:

    si te devuelve array mira que contesta.

    echo $soapclient->call( ‘hola’ , array(’name’ => ‘Mundo’) );

    cambialo por

    $resposta = $soapclient->call( ‘hola’ , array(’name’ => ‘Mundo’) );

    var_dump($resposta);

    un saludo!

Escribe un comentario