SOAP es un protocolo de intercambio para servicios web basado en XML, sobre el que puedes leer en esta entrada de la wikipedia. Para no liarnos con preámbulos, vamos con la chicha ¿cómo creamos un servicio web en PHP?.
Para facilitarnos la vida empezaremos por descargar NuSOAP, un toolkit para el desarrollo de servicios web con SOAP en PHP, que nos proveerá de diversas clases para trabajar con este protocolo. Basta con descargarlo, descomprimirlo, meterlo dentro de nuestro proyecto y, cuando queramos usarlo, incluir nusoap.php como librería.
Ok, con NuSOAP instalado toca crear un servidor SOAP en nuestra aplicación. Para el ejemplo crearemos un servidor, lo llamaremos producto.php, que si recibe una petición donde se le pida una lista de libros devuelva tres títulos (es un ejemplo básico, piensa que en la realiad podrías acceder a una base de datos y dar muchas más funcionalidades).
<?php require_once "nusoap.php"; function getProd($categoria) { if ($categoria == "libros") { return join(",", array( "El señor de los anillos", "Los límites de la Fundación", "The Rails Way")); } else { return "No hay productos de esta categoria"; } } $server = new soap_server(); $server->register("getProd"); $server->service($HTTP_RAW_POST_DATA); ?>
Ok, ahora necesitas un cliente, que llamaremos cliente.php. En el constructor, el cliente recibirá el url del servidor y para acceder al método que nos devuelve los libros recurriremos al método call(), al cual le pasaremos el nombre del método del servidor al que queremos acceder y los parámetros en forma de array. Además, también controlaremos que no haya errores en la comunicación.
<?php require_once "nusoap.php"; $cliente = new nusoap_client("http://localhost/producto.php"); $error = $cliente->getError(); if ($error) { echo "<h2>Constructor error</h2><pre>" . $error . "</pre>"; } $result = $cliente->call("getProd", array("categoria" => "libros")); if ($cliente->fault) { echo "<h2>Fault</h2><pre>"; print_r($result); echo "</pre>"; } else { $error = $cliente->getError(); if ($error) { echo "<h2>Error</h2><pre>" . $error . "</pre>"; } else { echo "<h2>Libros</h2><pre>"; echo $result; echo "</pre>"; } } ?>
Con esto ya tienes una idea múy básica del funcionamiento de un webservice SOAP construído con PHP. Pero claro, nos falta un archivo WSDL para tener un webservice decente. Aunque dicho archivo puede ser escrito a mano, NuSOAP puede generarlo por ti pasándole ciertos parámetros, por lo que lo ideal sería generarlo en el servidor. Así que modifica tu producto.php para que quede tal que así:
<?php require_once "nusoap.php"; function getProd($categoria) { if ($categoria == "libros") { return join(",", array( "El señor de los anillos", "Los límites de la Fundación", "The Rails Way")); } else { return "No hay productos de esta categoria"; } } $server = new soap_server(); $server->configureWSDL("producto", "urn:producto"); $server->register("getProd", array("categoria" => "xsd:string"), array("return" => "xsd:string"), "urn:producto", "urn:producto#getProd", "rpc", "encoded", "Nos da una lista de productos de cada categoría"); $server->service($HTTP_RAW_POST_DATA); ?>
Como ves, el cambio en es cuando llamamos a register, ya que en vez de pasarle, como antes, el método en cuestión, le añadimos también varios argumentos para generar el WSDL:
- El primer array nos permite definir el argumento de entrada y su tipo de datos
- El segundo define la función de retorno y su tipo de datos
- urn:producto es la definición del namespace
- urn:producto#getProd es donde definimos la acción SOAP
- Luego viene el tipo de llamada,que puede ser rpc, como en el ejemplo, o document
- Tras esto definimos el valor del atribute use, que puede ser encoded o literal
- Finalmente viene una descripción de qué hace el método al que llamamos
Ahora basta con que en el navegador accedas a producto.php?wsdl y verás el WSDL generado. Ya puedes copiarlo y añadirlo a tu directorio web (crea un archivo y llámalo, por ejemplo, libros.wsdl). Para que el cliente lo utilice debes modificar el código, y en el constructor, en vez del url le pasas el nombre del archivo, de forma que quede como en el ejemplo:
$client = new nusoap_client("libros.wsdl", true);
Ahora sí, ya tienes montado un pequeño servicio web. El ejemplo es simplón, pero piensa en todas las funcionalidades que podrías incorporarle.
Hola quisiera saber si me puedes ayudar con dos inconvenientes que tengo. He seguido tal cual tu tutorial pero cuando ejecuto cliente.php me aparece este error:
Error
wsdl error: Bad path to WSDL file libro.wsdl
Y libro.wsdl se encuentra en el mismo directorio que cliente.php, no entiendo que pasa ahí.
Por otro lado si intento mejor utilizar la dirección de producto.php?wdsl me aparece esto:
Error
Response not of type text/xml: text/html; charset=UTF-8
Entonces de ninguna forma me ha funcionado, me podrías dar una pista de algo que deba revisar??
Gracias.
chequea q tu servidor tenga instalado la libreria soap y tambien debes especificar bien el url y tambien al hacer el require la direccion de las carpetas
Muchas gracias por el aporte ha sido muy claro y especifico, obviamente es algo muy simple, pero no se necesita más para crear un web service, el resto es la complejidad que le quieramos dar nosotros mismo.
Muchas gracias por tu aporte
hola tambien tenia ese error, debes especificar bien el url y tambien al hacer el require la direccion de las carpetas
Hola, estoy siguiendo el ejemplo publicado pero al tratar de acceder a «https://ws/producto.php?wsdl», el navegador visualiza que no es posible mostrar la página …..
Sumamente interesante este protocolo, con el cual podemos crear Web Services de alto rendimiento
Gracias, muy claro y util
Muy util
mil gracias !!!!!!!! ya tengo mi primer WEB SERVICE SOAP !!!!!!! yujuuuuuuuu !!!
Pingback: Crear un webservice básico con PHP y SOA...
Hola, te agradezco por este post que me facilito el panorama de los web services.
Al probar el ejemplo, y acceder al client.php se queda como pegado esperando la respuesta, y despues de unos 15 segundos deja de cargar, no imprime ningún error, sabes a que se debe esto?
Que tal, me pasa lo mismo que a ti, pudiste solucionar el problema??…solo se queda cargando unos 30 segundos y al final no imprime nada…sin erro, sin informacion…
lo mas seguro es que tienes instalado appserv, instala xampp y prueba de nuevo.
O esta mal la manera en que accedo al servicio, segun yo para ver los resultados entro a localhost/miproyecto/client.php ?
Está muy claro tu ejemplo. Gracias.
Me indicaba un error en:
$server->service($HTTP_RAW_POST_DATA);
Pero le agregue lo siguiente y quedó sin problemas:
$HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : »;
Nuevamente gracias y saludos!
Donde pones $HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : ”; ?????
Eso mismo.
Si no mal entiendo la corrección quedaría de esta manera:
$server->service($HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA));
Hola, yo en el error de el $HTTP_RAW_POST_DATA lo corregí as:
$post = file_get_contents(‘php://input’);
$server->service($post);
Saludos!
Excelente tutorial amigo, muchas gracias 🙂
tengo un error al querer obtener el wdsl al seleccionar el wdsl me sale :
Error de lectura XML: contenido incorrecto tras un elemento XML del documento
Ubicación: http://localhost/webservice/producto.php?wsdl
Número de línea 2, columna 1:
Warning: Creating default object from empty value in /home/masqweb/Documentos/webservice/NuSOAP/lib/nusoap.php on line 75
^
y al querer usar el cliente me da un error de :
XML error parsing SOAP payload on line 2: Invalid document end
Me sale este error al usar un cliente
XML error parsing SOAP payload on line 2: Invalid document end
Así de primeras se me ocurre que puede que el WSDL esté mal formado. ¿En el servidor te da algún error o sólo te lo da con el cliente?. Puede que algún caracter no ASCII en el xml te la esté jugando.
usa esto
if ( !isset( $HTTP_RAW_POST_DATA ) )
$HTTP_RAW_POST_DATA =file_get_contents( ‘php://input’ );
$server->service($HTTP_RAW_POST_DATA);
Hola , me sale esto cuabndo veo el WSDL:
Este archivo XML no parece tener ninguna información de estilo asociada. A continuación se muestra el árbol del documento.
Hola amigos, muy bueno el tutorial. Pero me sale un error al ejecutar el cliente, lo escribo a continuación
Error
no operations defined in the WSDL document!
Gracias
Hola exelente tutorial.
Pero tengo una pregunta, necesito sacar una info de una tabla desde mysql, como hago esto?
Hola, muy buen tutorila facil y claro de hacer, pero tengo un problema en la funcion “function getProd” no puedo enviar los datos a otro lado porque me sale “HTTP Error: no data present after HTTP headers” y debo en esa funcion antes del join llamarla con los datos recibidos, gracias por la ayuda!
Amigo te hace falta una linea antes de:
$server->service($HTTP_RAW_POST_DATA);
Es esta:
$HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : ”;
El servidor quedaría:
require_once “nusoap.php”;
function getProd($categoria) {
if ($categoria == “libros”) {
return json_encode(array(
“El señor de los anillos”,
“Los límites de la Fundación”,
“The Rails Way”));
}
else {
return “No hay productos de esta categoria”;
}
}
$server = new soap_server();
$server->configureWSDL(“producto”, “urn:producto”);
$server->register(“getProd”,
array(“categoria” => “xsd:string”),
array(“return” => “xsd:string”),
“urn:producto”,
“urn:producto#getProd”,
“rpc”,
“encoded”,
“Nos da una lista de productos de cada categoría”);
$HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA)? $HTTP_RAW_POST_DATA : ”;
$server->service($HTTP_RAW_POST_DATA);
hola Rafael, tengo un web service, te podre pasar el link para que me ayudes hacer una prueba?? es que mi proveedor de pagina web me dice q esta bloqueado, y yo he podido accesar desde fuera de mi red. GRacias
GRACIAS!!!
Muy interesante el código, sobre todo por la ñ del «El señor de los anillos». En mi webservices no envio el caracter ñ en el reponse sino que me viene dado en el request. El problema es que no lo traga. Ya he cambiado la variable de nusoap.php a $soap_defencoding = ‘ISO-8859-1’; y ni por esas. ¿Alguna sugerencia? Muchas gracias
Podrías probar configurando el server en utf-8:
$server->soap_defencoding = ‘UTF-8’;
$server->decode_utf8 = false;
$server->encode_utf8 = true;
Y también el cliente:
$cliente->soap_defencoding = ‘UTF-8’;
$cliente->decode_utf8 = false;
Buen post, la verdad yo ignoraba cómo funcionaba un WebService.
Hasta ahora para las aplicaciones o sitios en los que necesitaba interactuar, yo enviaba requests ya sea por POST o GET a un .php y de este devolvía un XML o JSON con la data.
Esto en teoría reemplazaría a esta práctica, pero con más seguridad. ¿Es correcto? ¿O de alguna forma se puede ver o intervenir los parámetros de entrada y salida?
Saludos.
Saludos a todos, tengo un proyecto para iniciar en webservice, pero no le hallo mucho a esto, alguien podría asesorarme?, desde ya les agradezco, saludos.
Les explico, la idea es que de una base de datos capturada desde una pantalla de access se extraigan datos para que a su vez se conviertan en json con wsdl y puedan ser enviados a través del webservice, estara bien mi proceso o me brinque algo? La intensión es que se comparta la información generada en json hacia otros usuarios.
Amigo Juanxho, Parece que tendrás que leer mas sobre el Web service, creo que tienes un problema de concepto.
buenas tardes Amigo, tengo un web service, te podre pasar el link para que me ayudes hacer una prueba?? es que mi proveedor de pagina web me dice q esta bloqueado, y yo he podido accesar desde fuera de mi red. GRacias
No pues si estuvo bueno! Gracias al autor y al del comentario con el error que se resuelve con isset
escribo en la direccion localhost/producto.php?wsdl y no marca nada, muestra una pagina en blanco alguna recomendacion?
¿Conseguiste resolverlo? Tengo el mismo problema.
Hola,
me pasa lo mismo que a Diego, al hacer localhost/producto.php?wsdl no devuelve nada. He revisado la configuración del servidor y el php.ini y está todo correcto. ¿Alguna ayuda?
Dani ¿resolviste el problema?
Gracias y saludos.
Este el es código:
soap_defencoding = ‘UTF-8′;
$server->decode_utf8 = false;
$server->encode_utf8 = true;
$server->configureWSDL(«producto», «urn:producto»);
$server->register(«getProd»,
array(«categoria» => «xsd:string»),
array(«return» => «xsd:string»),
«urn:producto»,
«urn:producto#getProd»,
«rpc»,
«encoded»,
«Nos da una lista de productos de cada categoría»);
$HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA)? $HTTP_RAW_POST_DATA : ”;
$server->service($HTTP_RAW_POST_DATA);
?>
soap_defencoding = ‘UTF-8′;
$server->decode_utf8 = false;
$server->encode_utf8 = true;
$server->configureWSDL(«producto», «urn:producto»);
$server->register(«getProd»,
array(«categoria» => «xsd:string»),
array(«return» => «xsd:string»),
«urn:producto»,
«urn:producto#getProd»,
«rpc»,
«encoded»,
«Nos da una lista de productos de cada categoría»);
$HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA)? $HTTP_RAW_POST_DATA : ”;
$server->service($HTTP_RAW_POST_DATA);
?>
No quiere publicar el código completo :-(.
Muy bueno el codigo pero te hago una pregunta podrias armar un ejemplo, pasadole mas de un parametro a la función getProd, por ejemplo categoria y editorial
Si vas hacer un tutorial hazlo bien si no mejor no hagas nada solo traes confucion mejor otros resuelven el problema que tu
Hola Amigos, el primer ejemplo el WebService me salio, tuve un errorcillo pero era del path:
la carpeta donde esta el soap la tengo dentro demi proyecto nadamas basto con declarar la siguiente linea en ambos archivos:
require_once «nusoap/lib/nusoap.php»;
mi carpeta del proyecto se llama test, entonces cuando llame:
http://localhost/test/cliente.php
funciona perfecto (claro en cliente.php adecue el llamado a producto.php quedando de esta manera: $cliente = new nusoap_client(«http://localhost/test/producto.php»);
ejecute:
http://localhost/test/cliente.php
y me trae el resultado correcto:
Libros
El señor de los anillos,Los límites de la Fundación,The Rails Way
ahora cambie el producto.php como aconsejan accedo a:
http://localhost/test/producto.php?wsdl
y me marca el siguiente error:
This page contains the following errors:
error on line 2 at column 1: Extra content at the end of the document
Below is a rendering of the page up to the first error.
que me estara fallando? les agradezco.
Mi objetivo final son 2:
1) extraer informacion de una BD similar a como esta el ejemplo.
2) insertar datos (enviarle al webservice datos y que los inserte en una tabla) nos e como hacerlo, alguna idea de como investigar?
Gracias.
Ahh y de paso a este WebService, como pasarle datos, ejemplo: Si el llamado al webservice sea: http://localhost/test/cliente.php que liste TODOS los libros, pero si es asi:
http://localhost/test/cliente.php?libro=2
Que me traiga el libro 2.
Compartan y comenten saludos.
¡¡Muchas gracias amigo!! Me costó un montón encontrar un artículo que explicase de forma sencilla, clara y certera como hacer esta operación. Me fue muy útil, y te lo agradezco de verdad. Saludos.
Me sale el siguiente error: Response not of type text/xml: text/html
He revisado que tengo la librería nusoap.php en la carpeta correcta. Y los ficheros clientes.php y producto también. Cree el fichero libros.wsdl tal como indicaste.
Los he incluido todos en la misma carpeta pero no me funciona.
Puedes ayudarme.
Muchas gracias.
Ya me funciona, creo que al grabar el fichero wsdl con un editor eligiendo un formato inadecuado puede dar ese problema…
muy claro y tan fácil como copiar, pegar y probar. muy buen aporte.
a mi me funciono correctamente.
tengo la carpeta miservicio/lib/[archivos de nuSOAP]
tengo mis ficheros:
+ miservicio
|-+ [lib] (carpeta de nusoap)
|– micliente.php
|– servicio.php
|– servicio.config.php (opcional) para la creacion del
|– servicio.wsdl (guarda el contenido creado en ejecutar servicios.config.php), copiar y pegar
los contenidos son:
servicio.php
—————-
register(«getProd»);
$server->service($HTTP_RAW_POST_DATA);
?>
micliente
————-
getError();
if ($error) {
echo «Constructor error
«;
}
$result = $cliente->call(«getProd», array(«categoria» => «libros»));
if ($cliente->fault) {
echo «Fault
«;
}
else {
$error = $cliente->getError();
if ($error) {
echo «Error
«;
}
else {
echo «Libros
«;
}
}
?>
servicio.config.php
————————-
configureWSDL(«producto», «urn:producto»);
$server->register(«getProd»,
array(«categoria» => «xsd:string»),
array(«return» => «xsd:string»),
«urn:producto»,
«urn:producto#getProd»,
«rpc»,
«encoded»,
«Nos da una lista de productos de cada categoría»);
$server->service($HTTP_RAW_POST_DATA);
?>
servicio.wsdl
—————–
Nos da una lista de productos de cada categoría
# descripcion:
# —————-
/*
al ejecutar en el navegador servicio.config.php devolvera el xml generado del wsdl, lo copias y pegas en el fichero servicio.wsdl y ese fichero lo asignas en tu cliente.
$cliente = new nusoap_client(«servicio.wsdl», true);
el tutorial esta muy bien explicado pero si lo quieren masticadito aqui esta, facil y asi revisan en que fallan a la hora de implementarlo
*/
creo q al pegar el código y comentarlo se desarmo pero el contenido es lo que el autor del post coloco como ejemplo.
reemplazando servicio.php con el primer codigo
reemplazando servicio.config.php con el tercer codigo el que genera el xml
y reemplazando cliente.php con el segundo codigo que consume el servicio
Buenas Giapiere, existe posibilidad de hacerte una consulta?
Excelente, me sirvió mucho
Muchas gracias un gran aporte
Hola buenas tardes, he leido tu artículo y me parece bastante intersante.
Pero me gustaría hacerte una pregunta. ¿Cómo puedo hacer lo mismo que hace SOAPui pero sin usarlo? Tengo que hacer un testeo autoático de tres valores que pregunto con SOAP a un servidor, pero esta acción la tengo que automatizar para que haga este testeo un número «X» de veces.
Muchas gracias de antemano.
Buenas tardes,
Tengo que hacer un proyecto, con web services y no tengo mucha idea (para qué mentir).
El problema, es que el web service, ya lo tengo montado, para mi es una caja negra, a la que ingreso una serie de datos y esta me tiene que devolver unos campos.
Por así decirlo mi servicio web, me logueo, y luego en una caja de texto meto un número de teléfono y dando al botón de comprobar, este me devuelve una serie de campos que me muestra por pantalla.
Pues bien, me gustaría poder hacer una consulta masiva y poder mostrar esos campos en un excell.
Me podeis echar una mano?
Gracias de antemano.
Muy util.Gracias. Funciono de primera!
Qué diferéncia hay entre este WebService y una petición normal al servidor a través de php usando Ajax?
Lo pregunto porque estoy acostumbrado a hacer aplicaciones de gestion web y a cada rato estoy haciendo peticiones a la base de datos con php y realizando la llamada con ajax para no tener que recargar la pagina.
Con un WebService puedes acceder a la información alojada en cualquier servidor (através del propio WS que te sirve como puente), con AJAX sólo se puede acceder a la información del servidor en el que se ejecuta el script de PHP que mandas a llamar, y este script puede contener la información de consulta a BD directamente, sin ser un puente.
Esto debido a la Política del mismo origen.
Si quieres mostrar en tu servidor A información que está en una BD en el servidor B, haces un WS que instalas en el servidor B y que consultarás desde el servidor A.
Esto con AJAX no se podría, sino me crees inténtalo y si lo logras: compártelo 😉 😀
Saludos.
Esta bien si, es que no lograba ver la diferencia con este ejemplo. Ya me ha quedado claro, una conexión entre servidores. Gracias por la aclaración.
Saludos muchas gracias por la informacion !!!
Una duda cuales son las diferencias o ventajas frente a que si decido crear o simular un servicio web solo con solicitudes GET o POST osea de manera manual sin usar protocolos ni especificaciones
eres el amo del universo es justo lo que necesitaba milll gracias
¿como retorno Arrays?