Inicio > Aplicación, Delphi, PHP, WebService > (2/5) Generación del Webservice en PHP.

(2/5) Generación del Webservice en PHP.

Share Button

imagesContinuando en el lugar dónde nos quedamos en la primera entrada, vamos a pasar al siguiente punto. La generación del Servidor.

“ROADMAP” DE LAS ENTRADAS

Antes de comenzar a generar código, necesitamos generar la Base de Datos, de esta forma podremos ir realizando pruebas sobre ella.
Para la creación de la tabla de «usuario» podéis utilizar la siguiente sentencia:

 

CREATE TABLE IF NOT EXISTS `agenda` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`nombre` VARCHAR(30) NOT NULL,
`apellidos` VARCHAR(40) NOT NULL,
`telefono` VARCHAR(9) NOT NULL,
`extension` INT(11) DEFAULT NULL,
`departamento` VARCHAR(15) DEFAULT NULL,
`interno` INT(11) NOT NULL,
`email` VARCHAR(40) DEFAULT NULL,
PRIMARY KEY (`id`)

GenerateData Os adjunto también el siguiente fichero que incluye 100 registros para realizar pruebas. Está generado desde la web GenerateData que me ha parecido fantástica para crear este tipo de datos. Sin duda debe ir a parar a la  lista de favoritos. Podéis configurar las columnas de la tabla, los tipos de datos, el número de registros, incluso las máscaras para aquellos campos “no-estándars” de forma muy sencilla. Una vez completado este paso previo, se genera el fichero con las sentencias SQL para ejecutar en la Base de Datos.

Ahora que ya  tenemos la/s tabla/s, vamos a entrar en  detalle en el Servicio.

Aunque el código es sencillo, lo dividiré en partes, para ir explicando cada una de ellas por separado, aunque como he dicho son bastante evidentes.

(1)  Tratamiento de parámetros de entrada.

Está explicado en los comentarios del código, aun así podemos ver que tenemos dos parámetros que podemos pasar a la llamada; NUM y USER.

Una vez que se han determinado los dos parámetros se «prepara» la sentencia SQL.

    • USER: Permite buscar un usuario por el campo ID (Clave primária numérica que lo identifica de forma única).
    • NUM: Número de usuarios a recuperar desde el WebService. No se tiene en cuenta si se ha especificado el parámetro USER.

NOTA IMPORTANTE: Por problemas con el pluging del blog que muestra código, en los códigos PHP veréis que aparece =v, en realidad debéis sustituirlo por =>. Ya que el plugin si dejo el original no me lo escribe correctamente.

num => Número de registros a devolver.
n           Número concreto de registros
1           Todos
?            Si no se especifica por defecto se devuelven 10
user => Usuario a buscar (id); si no se introduce son todos
// parámetros ----------------------------------------------------------------
// num : Número de registros a devolver.
//        n       Valor concreto de registros
//        -1      Todos
//        ?         Si no se especifica por defcto se devuelven 10
// user : Usuario a buscar (id); si no se introduce son todos
// ---------------------------------------------------------------------------
// 10 valor por defecto
$number_of_users = isset($_GET['num']) ? intval($_GET['num']) : 10;  
  // Se ha introducido el parámetro user y es válido?
  if(isset($_GET['user']) && intval($_GET['user'])) {
    $user_id = intval($_GET['user']);
    $query = "SELECT * FROM `-BASEDATOS-`.`agenda` WHERE id=$user_id";
  }
  else
  {
    // Se ha especificado -1?
    $query = "SELECT * FROM `-BASEDATOS-`.`agenda`";
    if ($number_of_users == -1) {
    }
    else
    {
    $query = "SELECT * FROM `-BASEDATOS-`.`agenda` LIMIT $number_of_users";
    }
  }

(2) Conexión a la Base de Datos.

El código de conexión es bastante estándar y siempre similar. Basta configurar los valores de acceso (usuarios, password, servidor y nombre de la Base de Datos).

// Conectar a la Base de Datos
$link = mysql_connect("localhost", "-USUARIO-", "-PASSWORD-") or 
  die('No se ha podido conectar con la Base de Datos.');
mysql_select_db('-BASEDATOS-',$link) or 
  die('No se ha podido acceder a la Base de Datos.');
(3) Ejecución de la consulta.

La ejecución de la consulta (con los parámetros que hayamos configurado) y la recogida del resultado se hace de la siguiente manera.

  
// Lanzar la Query
$result = mysql_query($query,$link) or 
   die('Query errónea:  '.$query);
(4) Recuperar el resultado de la consulta y formatearlo.

Definimos un array para recoger el resultado de la consulta. Posteriormente utilizamos un bucle WHILE que recorre los valores devueltos; Utilizando la función mysql_fetch_assoc (que obtiene un registro y posiciona el cursor en el siguiente) recorremos la respuesta y almacenamos los “registros” devueltos en un array.

Al acabar codificamos el array en formato JSON para devolverlo como resultado.

// Crear un array de registros
$arrusers = array();
if(mysql_num_rows($result)) {
  while($user = mysql_fetch_assoc($result)) {
    $arrusers[] = array('Usuario =v $user);
  }
}
// salida en el formato JSON
header('Content-type: application/json');
echo json_encode(array('Usuarios' =v arrusers));
(5) Finalmente cerramos la conexión.
// desconectar
@mysql_close($link);

Pues bien, con esto ya tenemos nuestro servidor. En este caso no hemos añadido control de seguridad (dependiendo de cómo sea la aplicación,  será indispensable), tal vez más adelante podamos extendernos en ese tema.

Para comprobar que funciona, basta con abrir el navegador y escribir alguna de las direcciones que os adjunto debajo y comprobar que el resultado es el que debería ser.

http://neftali.clubdelphi.com/agenda/listado.php
* Devuelve 10 usuarios (cantidad por defecto)

http://neftali.clubdelphi.com/agenda/listado.php?user=10
* Devuelve 1 usuario con ID=10

http://neftali.clubdelphi.com/agenda/listado.php?num=20
* Devuelve 20 usuarios

http://neftali.clubdelphi.com/agenda/listado.php?num=-1
* Devuelve TODOS los usuarios de la tabla

El fichero PHP lo podéis descargar desde aquí (al final también coloco todos los enlaces).

Ya he comentado que hay muchas librerías en PHP que nos pueden ayudar en la  programación del servicio. Podéis buscar en Internet y encontraréis mucha información y ejemplos para la autentificación, acceso a Base de Datos, tratamiento de arrays,… No es mi intención extenderme con este tema, aunque sí voy a tratar una en concreto. Me ha parecido especialmente útil, pues está pensada para facilitar el trabajo con WebServices.

images2 Se trata de la librería nuSOAP, que posee herramientas tanto para facilitar el desarrollo del Servidor, como del cliente (yo lo usaré para el primero). nuSOAP es de código abierto y podéis encontrarla en la página de SourceForge. Para usarla, basta con descargar el zip, colocar las librerías en una carpeta donde tenemos nuestro WebService y hacer referencia a ellas en el código.

Lo que voy a hacer, es generar una variante de nuestro servidor utilizando nuSOAP. Además, para ver otra forma de retornar datos, en este caso voy a trabajar con una estructura «compleja» (lo que PHP llama «ComplexType«), aunque internamene sigue siendo un array; De forma que en lugar de retornarlos, los voy a recibir en mi aplicación cliente (Delphi) como una Clase con una estructura similar a esta:

Estructura = class(TRemotable)
private
  FId: integer;
  FNombre: String;
  FApellidos: String;
  FTelefono: String;
  FExtension: integer;
  FDepartamento: String;
  FInterno: integer;
  FEMail: String;
published
  property Id: integer read FId write FId;
  property Nombre: String read FNombre write FNombre;
  property Apellidos: String read FApellidos write FApellidos;
  property Telefono: String read FTelefono write FTelefono;
  property Extension: integer read FExtension write FExtension;
  property Departamento: String read FDepartamento write FDepartamento;
  property Interno: integer read FInterno write FInterno;
  property EMail: String read FEMail write FEMail;
end;

ImagenWSDLPara esta versión voy a definir la función «ConsultaUsuario» que permite buscar un único usuario por su ID (similar a como hacíamos antes) y  ConsultaUsuarios que nos permitirá buscar varios usuarios por el campo nombre, de forma que podamos usar un LIKE en la consulta (búsqueda parcial), añadiendo caracteres comodín.

Además veremos cómo la librería nuSOAP nos genera automáticamente el ficherio WSDL de nuestro WebService de forma automática, facilitándole unos datos básicos para ello.

Este fichero WSDL, nos será muy útil a posteriori para poder importarlo desde el propio Delphi, como veremos en próximas entradas.

Añadiremos a nuestro fichero, la siguiente línea para poder utilizar nuSOAP.

//llamada a librería nusoap
require_once('lib/nusoap.php');

La definición de los tipos compuestos se hace de la siguiente manera; El tipo para un usuario, y a continuación el array de usuarios (Estructura y ArregloDeEstructuras):

 

// Definir el tipo para un usuario.
$servidor -v wsdl -v addComplexType(
        'Estructura',
        'complexType',
        'struct',
        'all',
        '',
          array(
            'Id' =v array('name' =v 'id', 'type' =v 'xsd:integer'),
            'Nombre'=v array('name' =v 'nombre', 'type' =v 'xsd:string'),
            'Apellidos'=v array('name' =v 'apellidos', 'type' =v 'xsd:string'),
	    'Telefono'=v array('name' =v'telefono', 'type' =v 'xsd:string'),
	    'Extension'=v array('name' =v 'extension', 'type' =v 'xsd:integer'),
	    'Departamento'=v array('name'=v 'departamento','type'=v 'xsd:string'),
	    'Interno'=v array('name' =v  'interno', 'type' =v  'xsd:integer'),
	    'EMail'=v array('name' =v 'email', 'type' =v  'xsd:string')
            )
      );
 
// Definir el array de la estructura
$servidor -v wsdl -v addComplexType(
      'ArregloDeEstructuras',
      'complexType',
      'array',
      'sequence',
      'http://schemas.xmlsoap.org/soap/encoding/:Array',
      array(),
      array(
        array('ref' =v  'http://schemas.xmlsoap.org/soap/encoding/:arrayType',
          'wsdl:arrayType' =v 'tns:Estructura[]'
        )
      ),'tns:Estructura');

El registro de los métodos en la librería nuSOAP, se hace de la siguiente manera:

 

// registrar la función de consulta de usuario (por ID)
$servidor -v register('ConsultaUsuario',
      array('id'=v 'xsd:integer'), //tipo de dato entrada
      array('return'=v 'tns:ArregloDeEstructuras'), //tipo de dato salida
      $ns, false,
      'rpc', //tipo documento
      'literal', //tipo codificacion
      'Documentacion de consultaUsuarios') ; //documentacion
 
// registrar la funcion de consulta de usuario (por nombre)
$servidor -v register('ConsultaUsuarios',
      array('nom'=v 'xsd:string'), //tipo de dato entrada
      array('return'=v 'tns:ArregloDeEstructuras'), //tipo de dato salida
      $ns, false,
      'rpc', //tipo documento
      'literal', //tipo codificacion
      'Documentacion de consultaUsuarios') ; //documentacion

Imagen1145

El resto del fichero es muy similar al que vimos anteriormente.

Lo podéis descargar desde aquí (al final también coloco todos los enlaces).

Para probar el webService podemos acceder a la siguiente dirección:

http://neftali.clubdelphi.com/agenda/listado2.php

Si todo ha ido bien, veremos una imagen como la que aparece a la derecha. Podemos acceder al WSDL generado y ver los métodos.

___________________________________________________________________

ENLACES:

Fichero PHP con el servidor web (primera versión; listado.php)

Librerías nuSOAP (http://sourceforge.net/projects/nusoap/)

Fichero PHP con el servidor web (segunda  versión)

 

LINKS:

Pruebas para testear el primer servidor:

http://neftali.clubdelphi.com/agenda/listado.php

http://neftali.clubdelphi.com/agenda/listado.php?user=10

http://neftali.clubdelphi.com/agenda/listado.php?num=20

http://neftali.clubdelphi.com/agenda/listado.php?num=-1

Pruebas para testear el segundo servidor:

http://neftali.clubdelphi.com/agenda/listado2.php

http://neftali.clubdelphi.com/agenda/listado2.php?wsdl

Vota este post
Subscribe
Notify of
guest

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

13 Comments
Inline Feedbacks
Ver todos los comentarios
Eliseo GN
10 years ago

Excelente artículo y muy bien explicado, ya quiero ver los siguientes :)

Saludos

Alberto
Alberto
10 years ago

Hola el artículo esta muy bien. Ya habia visto muchos ejemplos de este tipo en Internet pero ninguno explica para mi lo mas importante y es explicar como podemos ponerle seguridad a todo esto ya que claro si en vez un ejemplo fuese un ejemplo real todo el mundo que conozca la url tendrá acceso a estos datos. A ver si te animas a poner un artículo que explique como ponerle seguridad a esto.
Muchas gracias.

Alberto
Alberto
10 years ago

Ok, si pasando usuario y password en la URL y luego verificarlo por cada petición puede ser un nivel muy básico de seguridad. Pero pensaba en algo más seguro como uso de par de claves pública y privada o algo así.
Gracias por la respuesta, un saludo.

Crandel
Crandel
10 years ago

Hola Neftalí, excelente artículo como siempre.
Hace rato que quería leer un poco sobre webservice con php, pero no había hecho tiempo.
Pero siendo un artículo tuyo, lo leo con gusto.

Suerte

Horacio
Horacio
10 years ago

Hola excelente articulo, agradezco tu publicación de verdad, estoy por realizar una app movil en Rad Studio que extraiga datos del servidor con php, creo que esto me puede ser de gran ayuda, si conoces información extra te lo agradeceria. Saludos desde México.

giuliano
giuliano
9 years ago

Hola, con que motor creaste la base de datos? Podria ser con phpmyadmin, usando xampp en la pc servidor? Muy buenos tus aportes. Y me parece mejor hacerlo con php porque para crear un webservice con windows, es reocmendable usar windows server, y para eso hay que saber algo de redes y configuracion. Entonces teniendo xampp ¿como se accederia al localhost desde otra pc?

Saludos desde Argentina

Giuliano
Giuliano
9 years ago

Hola de vuelta Neftalí, me parece que para que el tutorial me sirva deberia hacer mi propio webservice, de hecho estoy desarrollando una aplicacion en delphi para un negocio con distintas sucursales. Y entonces se me ocurre preguntarte a lista de pasos, deberia repetir los pasos solo que para mi aplicacion.
Primero debo tener una consulta en php para cada dato que necesite obviamente.
Luego todo el codigo desde la clase TRemotable va en delphi?
Me puedes decir como se arma la clase? Es enb private los parametros y en published los read y write. En que unidad del cliente en delphi va esto?

Alveiro Fernandez Leal
3 years ago

Muchas gracias, valoro mucho toda esta información… Espero seguir conectado con tu Blog.

13
0
Would love your thoughts, please comment.x
()
x