Construction
d'un serveur PHP web-services
Problématique U-Portal
Dans certaines universités (notamment Nancy2), il existe un existant
important en matière de développement PHP. Le but de ce document
est d'étudier la faisabilité de la création d'un serveur
de web-services PHP se greffant sur une application existante puis son intégration
dans le UPortal.
Installation de la librairie PEAR::SOAP
- Il existe deux grandes librairies PHP dédiées aux web-services
: celles de PEAR et celles de NuSphere qui s'appuient toutes deux sur une
même base.
- Toutes deux sont encore en version béta et n'offrent pas la même
stabilité et qualité que leurs équivalents Java.
- Par commodité, j'ai choisi la librairie SOAP qui se télécharge
ici : http://pear.php.net/package-info.php?pacid=87
- Penser aussi à installer tous les packages liés : HTTP, Net...
Un exemple simple : retourner le nom d'un étudiant connaissant son
numéro INE + clé
- Si on fait une rapide analyse orientée WSDL nous dit qu'il nous faudra
:
- un message entrant avec le code ine et la clé concatenés
de type string
- un message sortant avec le nom de l'étudiant (type string)
- la levée d'une exception dans le cas d'un étudiant inconnu
- La première chose à faire est d'inclure les librairies PEAR
nécessaires :
require_once('SOAP/Server.php');
- Ensuite, il faut créer une classe qui va 'abriter' les fonctions
de notre web-service :
class ws_apogee
/**
* fonction qui retourne le nom d'un étudiant connaissant son INE + clé
* @access public
* @param p_INE string code INE + clé de l'étudiant
* @return string nom de l'étudiant
*/
function getNomAvecINE($p_INE) {
return "ziller";
}
}
- Ensuite il faut enregistrer notre classe comme fournissant un service web
:
$ss = new SOAP_Server();
$sc = new ws_apogee();
$ss->addObjectMap($sc, 'urn:ws_apogee');
$ss->service($HTTP_RAW_POST_DATA);
Un client php pour appeller notre service-web
- il faut d'abord inclure les librairies SOAP clientes : require_once('SOAP/Client.php');
- ensuite, définir un endpoint, c'est à dire l'URL pointant
vers notre service web : $endpoint
= 'http://testoz.univ-nancy2.fr/mdw2003/ws/apogee.php';
- Ensuite il faut instancier un nouveau client SOAP vers cet endpoint : $sc
= new SOAP_Client($endpoint);
- la méthode call qui permet d'appeller notre service web prend 3 paramètres
:
- le nom de l'opération à exécuter :
$method = 'getNomAvecINE';
- les paramètres d'appel de l'opération : $params
= array('p_INE' => '1293010308M');
- des options contenant notamment le namespace à utiliser : $params
= array('p_INE' => '1293010308M');
- ensuite, il n'y a plus qu'a appeller notre service-web : $res
= $sc->call($method, $params, $options);
- enfin il faut afficher le résultat :
print_r($res);
Le document WSDL correspondant
- Comment interfacer ce service-web php avec Java. En l'état ce n'est
pas faisable
- Il nous faut un document wsdl si nous voulons utiliser WSIF.
- La tentative pour écrire manuellement
le fichier wsdl n'a pas pu être menée à bien.
Faute de pouvoir tracer les messages soap j'ai abandonné.
Génération automatique du WSDL
- PEAR::SOAP offre la possibilité de générer automatiquement
le fichier WSDL correspondant
- Pour cela il faut ajouter un constructeur à notre classe qui va lister
les différentes opérations et éventuellement les types
particuliers
- Ce qui nous donne :
function ws_apogee()
{
$this->__dispatch_map['getNomAvecINE'] = array( 'in' => array('input' => 'string'), 'out' => array('return' => 'string'));
}
- le tableau __dispatch_map liste les différentes opérations
et y associe les paramètres en entrée et en sortie
- le tableau __typedef permet lui de définir les types. Il est à
noter que cette définition automatique est assez basique et si on voulait
utiliser toutes les possibilités de XML Schéma il faudrait revoir
manuellement le fichier wsdl
- Ensuite, il faut traiter le cas où l'on demande à voir le
fichier wsdl (passage du paramètre wsdl au service web) :
if (isset($_SERVER['REQUEST_METHOD']) &&
$_SERVER['REQUEST_METHOD']=='POST') {
$ss->service($HTTP_RAW_POST_DATA);
} else {
require_once 'SOAP/Disco.php';
header("Content-type: text/xml");
$disco = new SOAP_DISCO_Server($ss,"ws_apogee");
if (isset($_SERVER['QUERY_STRING']) &&
strcasecmp($_SERVER['QUERY_STRING'],'wsdl')==0) {
echo $disco->getWSDL();
} else {
echo $disco->getDISCO();
}
exit;
}
Invocation à l'aide de WSIF
- Il semble que l'on soit obligé de garder la notation urn: utilisé
par PEAR::SOAP. Pourquoi?
- Pour que cela fonctionne il a fallu changer la ligne
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/wsdl/http/"/>
en
<soap:binding style='rpc' transport='http://schemas.xmlsoap.org/soap/http'/>
et pourtant, seule la première URL fonctionne!!
- Cela fonctionne mais j'ai toujours un warning :
- WSIF0006W: Plusieurs WSIFProvider trouvÚs, supportant l' URI du mÛme espace de nom
'http://schemas.xmlsoap.org/wsdl/soap/org.apache.wsif.providers.soap.apacheaxis.WSIFDynamicProvider_ApacheAxis,
org.apache.wsif.providers.soap.apachesoap.WSIFDynamicProvider_ApacheSOAP') trouvÚ.
- WSIF0007I: Utilisation de WSIFProvider 'org.apache.wsif.providers.soap.apacheaxis.WSIFDynamicProvider_ApacheAxis'
pour namespaceURI 'http://schemas.xmlsoap.or g/wsdl/soap/'.
Conclusion (provisoire)
- La librairie PEAR::SOAP est très mal documentée
- On travaille donc un peu à l'aveuglette et j'ai des doutes sur la
pérennité de ce produit dans le sens ou je pense, qu'avec les
nouvelles versions de PHP elle sera sans doute profondément remaniée
(voir remplacée par une extension native php pour les web-services).
- L'interopérabilité est vraiment faible : entre wsif (java),
delphi et php il est très compliqué d'arriver à un résultat
pour un web-service tout simple. J'ai un peu peur avec quelque chose de plus
compliqué.