sábado, 20 de julio de 2013

Web Services JSON con PHP

En este ejemplo vamos a intentar explicar cómo realizar un simple web service que utiliza JSON como formato de intercambio, en lugar del clásico XML que utilizan los web services SOAP. Con JSON además de su sencillez para manejarlo con Javascript y PHP tenemos un formato ligero y muy simple de notación literal.

Lo primero que tendremos en cuenta es que el formato de intercambio será JSON, por lo que la información enviada y recibida será de tipo application/json.

El código de la clase del web service y la implementación de una función básica para obtener la hora del servidor sería este:


class JSON_WebService {
    private $methods, $args, $strcall;
    public function __construct($rawData) {
        $this->strcall = str_replace($_SERVER["SCRIPT_NAME"]."/", "", $_SERVER["REQUEST_URI"]);
        $this->args = $rawData;
        $this->methods = array();
        header('Access-Control-Allow-Origin: *');
        header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
        header('Cache-Control: no-cache, must-revalidate');
        header('Content-type: application/json; charset=utf-8');
    }

    public function Register($name) {
        $this->methods[$name] = true;
    }

    public function Remove($name) {
        $this->methods[$name] = false;
    }

    private function call($name, $args) {
        if ($this->methods[$name] == true) {
            $result = call_user_func_array($name, $args);
           return json_encode($result);
        }
    }

    function start() {
        try{
            if(!function_exists($this->strcall))
                throw new Exception("Function '".$this->strcall."' does not exist.");
            if (!$this->methods[$this->strcall])
                throw new Exception("Access denied for function '".$this->strcall."'.");

            header("HTTP/1.0 200 OK");
            print $this->call($this->strcall, json_decode($this->args));
        }
        catch(Exception $e){
            header("HTTP/1.0 500 Internal server error");
            print json_encode(
                array(
                    "message" => $e->getMessage(),
                    "code" => $e->getCode(),
                    "file" => $e->getFile(),
                    "line" => $e->getLine(),
                    "stackTrace" => $e->getTrace(),
                    "status" => array("message" => "Internal server error", "code" => "500")
                )
            );
        }
    }
}

//Obtiene el contenido de la solicitud POST
$HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : ''; 
 
//Instancia de la clase JSON_WebService
$server = new JSON_WebService($HTTP_RAW_POST_DATA);
 
//Registra los metodos del servicio web
$server->register("getServerTime");
 
//Inicializa el servicio
$server->start();
 
//Define los metodos del servicio web
function getServerTime($format){
     return date($format);
}
Para la llamada al web service implementamos una clase cliente. Realmente lo que hacemos es utilizar las funciones de la librería libcurl pasándole por POST los parámetros a la página PHP que hace de servidor. El código lo tenemos a continuación:

class JSON_WebClient{
    private $URL;
    public function __construct($url){
        $this->URL = $url;
    }

    public function call($method, $args, $successCallback = false, $errorCallback = false){
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_HTTPHEADER, Array("Content-Type: application/json"));
        curl_setopt($ch, CURLOPT_URL, $this->URL."/".$method);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($args));
        $resposeText = curl_exec($ch);
        $resposeInfo = curl_getinfo($ch);
        
        if($resposeInfo["http_code"] == 200){
            if($successCallback)
                call_user_func($successCallback, json_decode($resposeText));
        } else {
            if($errorCallback)
                call_user_func($errorCallback, json_decode($resposeText));
        }
    }
}
Y la llamada la tendríamos con este código:
    $client = new JSON_WebClient("http://localhost/service.php");
    $client->call("getServerTime", array("format"=>"d/m/o H:i:s"), "onSucceededCallback", "onErrorCallback");
    
    function onSucceededCallback($result){
        print $result;
    }
    
    function onErrorCallback($error){
        print "Error: ".$error->{"message"};
    }

2 comentarios:

  1. Buen dia.

    Muchas Gracias por tu explicación. Necesito ademas saber cómo puedo tener el código WSDL correspondiente. Me podrías ayudar con ésto?

    ResponderEliminar
    Respuestas
    1. Hola Víctor Hugo,

      WSDL es un formato XML que se suele utilizar para las definiciones de las funciones de los web services SOAP. En este caso se maneja JSON pero no mediante SOAP, sinó con una llamada HTTP y lo que hace la parte servidor es devolver el resultado como application/json.

      Eliminar