Webservices – JSON

Webservices – JSON – Ejemplo simple

¿Qué nos dice Wikipedia de los Web Services?

Un servicio web es una tecnología que utiliza un conjunto de protocolos y estándares que sirven para intercambiar datos entre aplicaciones. Distintas aplicaciones de software desarrolladas en lenguajes de programación diferentes, y ejecutadas sobre cualquier plataforma, pueden utilizar los servicios web para intercambiar datos en redes de ordenadores como Internet. La interoperabilidad se consigue mediante la adopción de estándares abiertos.

Cuenta con una interfaz descrita en un formato procesable por un equipo informático (específicamente en WSDL), a través de la que es posible interactuar con el mismo mediante el intercambio de mensajes SOAP, típicamente transmitidos usando serialización XML sobre HTTPS conjuntamente con otros estándares web.

¿Qué nos dice Wikipedia de JSON?

JSON (acrónimo de JavaScript Object Notation, «notación de objeto de JavaScript») es un formato de texto sencillo para el intercambio de datos. Se trata de un subconjunto de la notación literal de objetos de JavaScript, aunque, debido a su amplia adopción como alternativa a XML, se considera (año 2019) un formato independiente del lenguaje.

Una de las supuestas ventajas de JSON sobre XML como formato de intercambio de datos es que resulta mucho más sencillo escribir un analizador sintáctico (parser) para él. En JavaScript, un texto JSON se puede analizar fácilmente usando la función eval(), algo que (debido a la ubicuidad de JavaScript en casi cualquier navegador web) ha sido fundamental para que haya sido aceptado por parte de la comunidad de desarrolladores AJAX.

¿Qué ejercicio deseo presentaros?

Mi idea es que podáis ver lo sencillo, rápido y eficiente que es utilizar PHP para crear Webservices y para utilizar JSON como formato de transmisión de datos.

Para construir la parte del servidor de los Webservices utilizo el framework de Zend ( ahora LÁMINAS) que hace todo muy simple y que nos facilita el interfaz del WSDL, que permitirá a cualquiera saber cómo acceder al servicio y qué métodos (funciones) están publicadas.

El ejemplo hecho en PHPRunner es muy sencillo, ejecuta la parte del cliente del Webservices, obtiene a través de este mecanismo los Municipios de una Provincia y los carga en una tabla con un campo añadido del identificativo de la sesión de trabajo para el usuario conectado, de tal forma que los datos transmitidos los veremos en una tabla, con datos diferentes para cada usuario conectado.

Como veis, el ejercicio no tiene más sentido de ver las 2 tecnologías (Webservices y Json), más una forma de presentar los datos obtenidos de esta forma, en el formato que PHPRunner 10.2 sabe hacerlo muy bien.

Podéis ver el resultado del ejemplo en https://fhumanes.com/consume_ws/ . La opción de “Municipio”, solicita el código de la Provincia y trae, utilizando el Webservices y el formato de datos JSON, los Municipios de dicha Provincia.

Paso a describir los fuentes que entiendo son más interesantes:

Ficheros para construir el Server del Webservices

Este fichero de configuración o estos datos los requerimos tanto para la parte Server como para la parte Cliente.

<?php
  define("URI","http://localhost/consume_ws/server");
  define("LOCATION_WSDL","http://localhost/consume_ws/server/server_wsdl.php");
  //  define("SOAP_VERSION", "SOAP_1_2");
  define("WSDL","http://localhost/consume_ws/server/server_wsdl.php?wsdl");
?>

Para crear el Webservices utilizando Laminas Framework lo que se hace es crear una clase y las funciones (métodos del webservices) que necesitemos.

Muy importante es la parte de comentarios de antes de las funciones. El literal @param y @return se va a utilizar para establecer el tipo de variable que van a tener los parámetros de entrada y la variable de respuesta.

En este caso el código es:

<?php
class AccesoMunicipios {
    
  /**
  * Access Municipios of Provincia
  * 
  * @param string $CodeProvincia
  * @return string
  */
    
  public function Municipios($CodeProvincia) {
    
   $conn = new mysqli('localhost', 'root', 'humanes', 'runner_reports'); // conection to Mysql
   if ($conn->connect_errno) { // If error conection to Mysql
    echo "Lo sentimos, este sitio web está experimentando problemas.";
    echo "Error: Fallo al conectarse a MySQL debido a: \n";
    echo "Errno: " . $conn->connect_errno . "\n";
    echo "Error: " . $conn->connect_error . "\n";
    exit;
  }
  // execute SQL
  $sql = "SELECT `idrp_municipio`, `CodigoMunicipio`, `NombreMunicipio` FROM rp_municipio where `CodigoProvincia` = '$CodeProvincia'";
  if (!$result = $conn->query($sql)) {
    // ¡Oh, no! The query error. 
    echo "Lo sentimos, este sitio web está experimentando problemas.";
    echo "Error: La ejecución de la consulta falló debido a: \n";
    echo "Query: " . $sql . "\n";
    echo "Errno: " . $conn->errno . "\n";
    echo "Error: " . $conn->error . "\n";
    exit;
  }

  if ($result->num_rows === 0) {
    // ¡Oh, not record 
    echo "Lo sentimos. No se pudo encontrar una coincidencia para el Código $CodeProvincia. Inténtelo de nuevo.";
    exit;
  }

  $municipios = $result->fetch_all(MYSQLI_ASSOC);
  $municipios = json_encode($municipios, JSON_UNESCAPED_UNICODE); // convert Array to Json

  // free resource of Mysql
  $result->free();
  $conn->close();

  return $municipios;
    }
  }
?>

Lo que hace este código es recibir un parámetro con el código de la Provincia, accede a la BD y recupera todos los Municipios de dicha Provincia en una Array y después transforma dicho Array a un formato JSON, que es lo que transmite.

El resto de código del servidor es:

<?php
require_once 'laminas-soap_2.10.0/autoload.php';

require_once("configuracion_wsdl.php");
require_once("clases_AccesoMunicipios.php");


try {
  if (isset($_GET['wsdl'])) {
    $autodiscover = new Laminas\Soap\AutoDiscover();
    $autodiscover->setClass('AccesoMunicipios')->setUri(LOCATION_WSDL)->setServiceName('TestWebserive');
    header('Content-type: application/xml');
    echo $autodiscover->generate()->toXml();
  } else {
    $options = [
        'soap_version' => SOAP_1_2,
        'actor'        => LOCATION_WSDL,
        'encoding'     => 'UTF8',
        'uri'          => LOCATION_WSDL,
        'parse_huge'   => false,
    ];
    $servidorSOAP = new Laminas\Soap\Server(null,$options);
    $servidorSOAP->setClass('AccesoMunicipios'::class);
    $servidorSOAP->handle();
  }
} catch (SOAPFault $f) {
    print $f->faultstring;
}
?>

Normalmente, para comprobar que el Webservices funciona y no tiene problemas, suelo escribir un ejemplo de Cliente. Este cliente tiene 2 partes, una para probar la Clase (sin el protocolo de Webservices) y otra como Cliente del Webservices. En este caso el ejemplo es:

<?php
// Client example to test the webservice server

require_once("configuracion_wsdl.php");
/*
 * Class test directly, without communications
 */
/*
 require_once("clases_AccesoMunicipios.php");
 $AccesoMunicipios = new AccesoMunicipios();
 // Test
 $result = $AccesoMunicipios->Municipios('01');
 print_r($result);
 $result = json_decode($result,true);
 print_r($result);
*/

try {
  $client = new SoapClient(WSDL, array('location' => LOCATION_WSDL)); // Server wsdl access

  $result = $client->Municipios('01'); // Execution of a webservices method
  $result = json_decode($result,true); // Array decoding in JSON format
  // print_r($result);
  foreach ($result as &$municipio) { // Test to print the set of ARRAY elements
    $id = $municipio['idrp_municipio'];
    $CodigoMunicipio = $municipio['CodigoMunicipio'];
    $NombreMunicipio = $municipio['NombreMunicipio'];
    echo "id = $id, Código= $CodigoMunicipio, Nombre= $NombreMunicipio <BR>";
   }
  
} catch (SOAPFault $f) { // In case of error, printing of the same
  print $f->faultstring;
}

?>

En este ejemplo, lo que está comentado es el test de la Clase.

Pues como podéis apreciar, es muy simple construir la parte del servidor de los webservices en PHP y para aquellos que lo habéis hecho en Java u otro lenguaje de programación similar, podéis valorar mucho mejor lo sencillo, rápido y eficiente que es.

En este apartado explico el código hecho en PHPRunner

Recogemos el Id de la sesión, para establecerla como clave a la información que recuperemos. Evento “after application initialized

$_SESSION['session_name']=session_id();

En la tabla “temp_municipio” codificamos el evento “after table initialized

$session_name = $_SESSION['session_name'];
$query->addWhere("SessionName = '$session_name'"); // filter only this session

En la acción de “ADD” se codifica el evento “before record added“:

$session_name = $_SESSION['session_name'];
$provincia = $values['CodigoProvincia'];
// Client WebServices
require_once("server/configuracion_wsdl.php");

$client = new SoapClient(WSDL, array('location' => LOCATION_WSDL)); // Server wsdl access

$result = $client->Municipios($provincia); // Execution of a webservices method
$result = json_decode($result,true); // Array decoding in JSON format
// Delete record of Municipios after
$sql = "delete FROM temp_municipio where SessionName = '$session_name'";
DB::Exec($sql);
// Inser new record of Municipìos
foreach ($result as &$municipio) { // Test to print the set of ARRAY elements
    $id = $municipio['idrp_municipio'];
    $CodigoMunicipio = $municipio['CodigoMunicipio'];
    $NombreMunicipio = $municipio['NombreMunicipio'];
    $sql = "INSERT INTO temp_municipio (`SessionName`, `CodigoProvincia`, `CodigoMunicipio`, `NombreMunicipio`) 
                    Values ('$session_name','$provincia','$CodigoMunicipio','$NombreMunicipio')";
    DB::Exec($sql);
    // echo "id = $id, Código= $CodigoMunicipio, Nombre= $NombreMunicipio <BR>";
   }


//**********  Redirect to another page  ************
header("Location: temp_municipio_list.php");
exit();

return false;

Y así de simple ha quedado todo. Accede al Server, recupera todos los Municipios en formato JSON, los pasa a una matriz y uno a uno de los registros los inserta en la tabla temporal con el correspondiente Id de la sesión.

Como siempre, en mi blog están todos los fuentes para ser descargados y para cualquier consulta o lo que necesitéis, podéis contactar conmigo a través de mi email [email protected]

Adjuntos

Archivo Tamaño de archivo Descargas
zip Modelo de datos en formato Mysql Workbech 8 KB 470
zip Backup de la Base de Datos 83 KB 497
zip PHPRunner 10.7 + Server (directorio "files") 778 KB 684

Blog personal para facilitar soporte gratuito a usuarios de PHPRunner