Les services web fournissent un moyen simple de faire communiquer les applications. Au contraire de systèmes propriétaires tels que Corba ou RMI il permettent (au moins théoriquement) de faire communiquer des applications hétérogènes.
PHP5 fourni une extension SOAP en natif qui permet de mettre en place un web service très simplement.
Pour l’exemple, nous allons mettre en place un service qui permet des clients dans une base de données située sur le serveur (base clients de l’entreprise) serveur A. Nous accéderons à ce service depuis un client situé par exemple dans le back-office du site web hébergé sur un autre serveur, serveur B.
Le service sera comportera les éléments suivant :
- code serveur sur le serveur A (customers.php)
- fichier WSDL sur le serveur A (customers.wsdl)
- code client sur le serveur B (customers_search.php)
Le principe même d’un service web est d’assurer une communication entre 2 machines, un serveur et un (ou plusieurs) client(s).
Le serveur est implémenté de la manière suivante dans le fichier customers.php :
<?php class Customers{ function search($keywords){ /* on remplacera le code suivant par une recherche des données dans la base */ return array( array('id'=>1, 'first_name'=>'bob', 'bob'), array('id'=>2, 'first_name'=>'bill', 'bill') ); } } $wsdl = 'customers.wsdl'; $server = new SoapServer($wsdl); $server->setClass('Customers'); $server->handle(); ?>
Le fichier WSDL est un fichier XML, il a pour rôle de décrire le service : quelles méthodes sont accessibles, quelle données sont attendues en entrée, quelles données sont retournées, etc. Le but du jeu étant de pouvoir rechercher un service web et que sa description soit compréhensible par une machine.
Implémentation du fichier WSDL :
<code><?xml version='1.0' encoding='UTF-8'?> <!-- WSDL file generated by Zend Studio. --> <definitions name="customers" targetNamespace="urn:customers" xmlns:typens="urn:customers" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/"> <types> <schema xmlns="http://www.w3.org/2000/10/XMLSchema"> <complexType name="ArrayOfCustomers"> <complexContent> <restriction base="soapenc:Array"/> </complexContent> </complexType> </schema> </types> <message name="search"> <part name="keywords" type="xsd:string"/> </message> <message name="searchResponse"> <part name="searchReturn" type="ArrayOfCustomers"/> </message> <portType name="CustomersPortType"> <operation name="search"> <input message="typens:search"/> <output message="typens:searchResponse"/> </operation> </portType> <binding name="CustomersBinding" type="typens:CustomersPortType"> <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> <operation name="search"> <soap:operation soapAction="urn:CustomersAction"/> <input> <soap:body namespace="urn:customers" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </input> <output> <soap:body namespace="urn:customers" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </output> </operation> </binding> <service name="customersService"> <port name="CustomersPort" binding="typens:CustomersBinding"> <soap:address location="http://serveur-a/tests/web-services/customers.php"/> </port> </service> </definitions>
Ce fichier a été généré avec Zend Studio puis modifié légèrement. Créer les fichiers WSDL à la main serait très laborieux.
Implémentation du client, customers_search.php sur le serveur B :
$wsdl = 'http://serveur-a/tests/web-services/customers.wsdl';
$options = array(
'compression'=>true,
'exceptions'=>false,
'trace'=>true
);
$serv_customers = new SoapClient($wsdl, $options);
$customers_arr = $serv_customers->search('bob');
if (is_soap_fault($customers_arr)) {
echo 'fault : ';
var_dump($serv_customers->__getLastRequest());
var_dump($serv_customers->__getLastRequestHeaders());
} else {
echo '<pre>'.var_export($customers_arr, true).'</pre>';
}
En théorie, tout marche correctement. Dans la pratique, rien ne marche jamais. Donc si ça ne fonctionne pas :
- Appeler le fichier WSDL pour vérifier que c’est du XML bien formé (IE signalera une erreur si le XML est mal formé)
- Tester le serveur indépendemment
L’extension SOAP met les fichier WSDL en cache par défaut. Donc, si vous modifiez ce fichier, il faut supprimer la version en cache sur le « serveur client » (serveur B). Le comportement du cache de SOAP peut être modifié dans la section SOAP du php.ini.
L’appel d’un web service est une opération couteuse. Il vaut mieux grouper les appels plutôt que d’appeler un web service plusieurs fois dans un même traitement.
Quelques autres questions à creuser :
- sécuriser notre service web (sinon la terre entiere a potentiellement accès au SI de l’entreprise)
- réaliser un web service qui supporte les sessions (statefull)
N’hésitez pas à laisser un message si quelque chose ne semble pas clair.
1er QUESTION
Dans quel dossier doit être *.wsdl
Dans quel dossier customers.php
2er Comment voir que le service a bien été activer par « EasyPHP »
(Extention SOAP OK)
A+
Le fichier wsdl doit être accessible pour l’instanciation du client et du serveur.
Le client et le serveur sont instanciés en utilisant une URI.
cf. la doc.
Pour tester, le plus simple est de mettre le serveur (fichier php qui instancie le serveur Soap) et le wsdl dans le même dossier sur le seveur.