My kemenworld…

To mock or not to mock…

PEAR::Service_Webservice

Posted by kementeus en agosto 20, 2007

Desde hace ya varios años soy fiel defensor de la distribución de aplicaciones y la interoperatibilidad usando WebServices, uno de los lenguajes que comencé por explotar con esta tecnología fue PHP, claro, usando PEAR::SOAP, uno de los inconvenientes (en realidad hay varios) de PEAR::SOAP era lo dificil de escribir de cada implementación y lo aún más difícil de “debug” (créanme, a veces pasa a ser toda una pesadilla). Bueno, de unos meses para acá me topo con otro amigo que por lo menos para un par de cosas me facilitó bastante el trabajo, se trata de PEAR::Services_Webservice.

Al igual que su compañero PEAR::SOAP, PEAR::Services_Webservice tampoco está en versión estable, así que al instalarlo recuerden cambiar su configuración de PEAR a beta. A diferencia de PEAR::SOAP, en este módulo no hace falta escribir las tediosas partes del dispatch_map o crear (por cuestiones de claridad) el service server y luego el service dispatcher. No voy a tocar como se hace en PEAR::SOAP y entraré de lleno en cómo se implementa un servicio sencillo en PEAR::Services_Webservice. Antes de continuar debo avisar que deben tener la SOAP extensión instalada en PHP para que todo funcione como se espera, PHP5 ya la trae como default.

Comenzaremos con una clase sencilla, imaginemos que tenemos una clase que suma dos números:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<?php

class SeviceExample
{
    public function addNumbers($num1, $num2)
    {
    	return $num1 + $num2;
    }
}

?>

Bien, ahora, tomando en cuenta que ya tenemos instalado PEAR::Services_Webservice hagamos que nuestra clase sea ahora un servicio:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?php
require_once 'Services/Webservice.php';

class ServiceExample extends Services_Webservice
{
  /**
  * Add two integers
  *
  * @param int
  * @param int
  * @return int
  */
  public function addNumbers($num1, $num2)
  {
    return $num1 + $num2;
  }
  
  private function noService()
  {
  	// boooohhhh!!!
  }
  
}

$example = new ServiceExample(
  'service name',
  'service simple description',
  array(
    'uri' => 'ServiceExample',
    'encoding' => SOAP_ENCODED,
    'soap_version' => SOAP_1_2
  )
);

$example->handle();
?>

el método “handle” de la clase Services_Webservice se encarga de manejar los request y todo lo relacionado al servicio como tal, o sea, una vez llamado este método no tenemos que preocuparnos por nada en el momento de ejecutar una llamada o retornar la descripción del servicio. Al instanciar una clase hija de Services_Webservice debemos pasar como parámetros el nombre del servicio (“service name”), una simple descripción del servicio (“simple service description”) y un arreglo de opciones en el momento de instanciar la clase (el uri name del namespace correspondiente al servicio, el encoding por el cual serán transmitidos los datos y la versión de SOAP que se usará, por default creo que debemos usar para la versión y el encoding esos).

Como algunos sabrán, los mensajes SOAP tienen entre sus características ser tipificados, por lo que demos indicar siempre los tipos, en PEAR::SOAP esto lo hacíamos al inicializar el arreglo $__dispatch_map, esto aveces (en realidad casi siempre) complicaba un poco nuestro código. Services_Webservice tiene un “approach” mucho más fácil y eficaz, usar docstrings para identificar al servicio. La primera línea es tomada en cuenta como si fuera la descripción del método (para que simples mortales sepan que hace), luego los @param indican el tipo necesario para los parámetros, @return a su vez indica el tipo de retorno del método del servicio, tengan cuidado porque sus comentarios de docstring deben comenzar SIEMPRE con /**.

Imaginando que nuestra prueba esta en orden y en nuestro webserver preferido al acceder a este archivo (http://<server address>/wstest/example1.php) obtendremos algo así:

 services_webservice output example 1

Como verán por default nos retorna una página amigable con la descripción del servicio y con cada uno de los métodos asociados. Si quisiera acceder al WSDL document, simplemente debo agregarle ?WSDL al final del URL en mi request (o sea, http://<server address>/wstest/example1.php?wsdl)

Como también se han dado cuenta, sólo se publicaran métodos públicos, los privados son pasados de largo.

Qué pasa si quiero retornar un tipo no existente en la lista de tipos aceptados por SOAP o es un tipo complejo? Bien, la respuesta es sencilla, simplemente definimos un nuevo tipo, quizás algo como esto:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<?php
class MyReturn
{
	/**
	* @var int
	*/
	public $result;
	
	public function __construct($result)
	{
		$this->result = $result;
	}
}
?>

Ahora sólo tendríamos que agregar el include a esta clase con el nuevo tipo y cambiar el tipo de retorno de addNumbers a MyReturn. Fácil verdad?. Bien, qué si ahora quiero retornar arreglos? la respuesta es tan sencilla que ni siquiera pondré un ejemplo, simplemente agregamos al final del tipo [], de esta manera un arreglo de enteros pasaría a ser int[], uno de cadenas a string[] y uno de MyReturn a MyReturn[]. Sencillísimo!.

Para finalizar recuerden que Services_Webservice está en beta, por lo que aún pueden faltarle una que otra cosa, pero creo que para algo sencillo tendremos más que suficiente. Recuerden que necesitaran un cliente de su Webservice para probarlo como se debe. Como siempre comentarios a la orden.

8 comentarios to “PEAR::Service_Webservice”

  1. Jaime said

    Que te parece NuSOAP. Hace tiempo lo usaba y era bien simple. El problema es que creo ya esta olvidado el proyecto desde el 2005. Tal vez podría ser usado como cliente???

  2. kementeus said

    @Jaime:
    Creo que con PEAR SOAP_Client te sería más que suficiente para trabajar webservices como cliente, te lo recomiendo si antes usabas NuSOAP y quedaste esperando algo mejor, te va a gustar.
    Saludos

  3. Perelijillo said

    Esto es cuando usas soap como protocolo, pero si necesitas usar xml-rpc o rest, que libreria recomendarias ?

  4. kementeus said

    @perelijillo:
    Te refieres a publicar o consumir? para publicar XML-RPC puedes usar PEAR :: XML-RPC (ya hay un xml-rcp2) que publica tanto clientes como server xml-rpc. En el caso de REST no he visto mas que Zend_Rest_Server (de la Zend Framework) y un par de ejemplos usando cosas como HTTP Request de PEAR.

  5. Perelijillo said

    Gracias ! voy a investigar sobre HTTP Request.

    Saludos.

  6. Rodrigo said

    Hola kementeus, espero estes bien, me gustaría que me ayudaras a configurar o decirme como se instala esta herramienta, ya que la descarge y no se donde se instala para seguir con el ejemplo…te cuento que me urge aprender esto de los WS ya que me estan pidiendo implementar varios Ws utilizando php5, pero he tenido que lidiar con los archivos wsdl junto con el SOAP que me han dado mas de un dolor de cabeza, ya que no tengo bien claro como se generan, quizas esta herramienta me ayude de mejor manera…y los ejemplos que he encontrado en Internet son en su mayoria utilizando php4 y otros ni siquiera funcionan y los de php5 son muy muy escasos….espero me ayudes, que estes bien.

  7. kementeus said

    @Rodrigo:
    Te aconsejo que primero te des una vuelta por los manuales básicos de PEAR, no solo te ayudaran a entender “qué” esta pasando debajo del capó y cómo instalar cualquier “paquete” PEAR (o sea, todos los del repositorio oficial y algunos mas como los de Zend y/o phpUnit). La documentación de PEAR la puedes encontrar aquí: http://pear.php.net/manual/en/

    Saludos

  8. Arturo Aleé said

    Hola kementeus, me gustaría saber si me puedes ayudar con la parte de la seguridad del servicio, me gustaría que para poder utilizarlo deban de pasar su user y pass.

    Saludos.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

 
A %d blogueros les gusta esto: