Ecrire un Web Service en PHP – Partie 2 – Définir les services de l’interface

La première partie du sujet nous a permis d’introduire et présenter les Web Services. Nous avons ainsi introduit les notion suivantes : REST, WSDL, SOA, SOAP étant décrit dans des articles précédents, ainsi qu’une analyse de performance et de publication des Web Services.

Dans ce billet, nous allons voir maintenant comment réaliser l’implémentation d’un Web Service en 3 étapes :

  • Définir les services de l’interface, par l’intermédiaire du WSDL
  • Mettre en œuvre le service. Cela se fait avec le langage PHP.
  • Déployer le service sur votre serveur Web

Définir les services de l’interface

Nous allons essayer d’écrire notre propre Web Service SOAP, qui réalisera l’addition / soustraction de deux entiers.

La première tâche est de créer un document WSDL décrivant notre service dans un format compréhensible par les clients.

Contenu

Dans la mesure où il s’agit d’un standard basé sur XML, la structure du WSDL vous semblera familière si vous avez une connaissance un peu approfondie du XML. Le fichier WSDL se divise en plusieurs parties : un ensemble d’éléments décrivant les types de données utilisés par le service, les messages que le service peut recevoir, ainsi que les liaisons SOAP associées à chaque message.

Le document WSDL commence par l’entête XML standard contenant un identificateur de version <?xml version="1.0"?>
, et que l’élément racine du document se nomme <definitions>. Ce dernier, donnant le nom du service, peut prendre plusieurs attributs facultatifs, qui le décrivent et déclarent les espaces de noms utilisés (namespaces) à utiliser dans le reste du document.

Ensuite, les types complexes nécessaires pour la définition de l’interface du service sont définis au sein de l’élément types.

La section message définie deux messages. Le premier est getResultRequest, qui est une requête pour relayer le message getResult et prend deux paramètres de type int nommés : integer1, integer2 et un paramètre de type string nommée : operation.
L’autre message est getResultResponse, qui est la réponse au message getResult, contenant une valeur de type int, nommé result.

La section portType combine plusieurs éléments message pour composer une opération : getResult. Chaque opération se réfère à un message en entrée (input) et à des messages en sortie (output).

L’élément <binding> décrit les spécifications concrètes de la manière dont le Web Service sera implémenté et définit la façon dont les messages doivent être transmis. Il spécifie également les espaces de noms et la valeur de l’entête soapAction pour la méthode getResult.

Enfin, le service du document permet d’invoquer le service donné, ce qui sert à regrouper un ensemble de ports reliés (port). La plupart du temps, c’est une URL invoquant un service SOAP.

Conseils de création

Voici quelques conseils pour créer votre document WSDL :

  • Documentez toujours votre fichier WSDL, à la fois par le biais de la balise documentation, et en fournissant de la documentation dans un fichier externe au document WSDL
  • Utilisez la Recommendation 2001 de XML Schema
  • Utilisez l’élément type, dans tous les cas, ne faites pas référence aux types dans l’élément message.

Exemples

Je vais vous décrire pas à pas la construction du WSDL :

Partie 1 : Définitions

On commence par définir l’entête XML, puis l’élément definitions.

[sourcecode language="xml"]
<?xml version="1.0"?>
<!– partie 1 : Definitions –>
<definitions name=’getResult’
targetNamespace=’http://example.org/getResult’
xmlns:tns=’http://example.org/getResult’
xmlns:soap=’http://schemas.xmlsoap.org/wsdl/soap/’
xmlns:xsd=’http://www.w3.org/2001/XMLSchema’
xmlns:soapenc=’http://schemas.xmlsoap.org/soap/encoding/’
xmlns:wsdl=’http://schemas.xmlsoap.org/wsdl/’
xmlns=’http://schemas.xmlsoap.org/wsdl/’>

</definitions>
[/sourcecode]

Partie 2 : Message

[sourcecode language="xml"]

<message name=’getResultRequest’>
<part name=’operation’ type=’xsd:string’/>
<part name=’integer1′ type=’xsd:int’/>
<part name=’integer2′ type=’xsd:int’/>
</message>
<message name=’getResultResponse’>
<part name=’result’ type=’xsd:string’/>
</message>

[/sourcecode]

Partie 3 : Port Type

Un port est simplement une suite d’opérations. Dans de nombreux langages de programmation, on appelle ceci une bibliothèque, un module ou une classe, mais dans le monde des Web Services, les points de connexion sont des ports, et la définition abstraite d’un port est appelée « Type de Port ».

Ici, nous créons la définition abstraite d’une procédure getResult, en WSDL, dont l’input est le message d’invocation de la méthode, et l’output le message de retour de la méthode.

[sourcecode language="xml"]

<portType name=’getResultPortType’>
<operation name=’getResult’>
<input message=’tns:getResultRequest’/>
<output message=’tns:getResultResponse’/>
</operation>
</portType>

[/sourcecode]

Partie 4 : Binding

Cette partie va nous permettre de rattacher le port à SOAP. Les types de ports sont indépendants du protocole.
Ici, nous utiliserons des requêtes SOAP (soap:binding) de type RPC (style='rpc') via HTTP (transport='http://schemas.xmlsoap.org/soap/http') avec un encodage SOAP (encodingStyle='http://schemas.xmlsoap.org/soap/encoding/').

[sourcecode language="xml"]

<binding name=’getResultBinding’ type=’tns:getResultPortType’>
<soap:binding style=’rpc’ transport=’http://schemas.xmlsoap.org/soap/http’/>
<operation name=’getResult’>
<soap:operation soapAction=’urn:xmethods-delayed-quotes#getResult’/>
<input>
<soap:body use=’encoded’ namespace=’urn:xmethods-delayed-calcul’
encodingStyle=’http://schemas.xmlsoap.org/soap/encoding/’/>
</input>
<output>
<soap:body use=’encoded’ namespace=’urn:xmethods-delayed-calcul’
encodingStyle=’http://schemas.xmlsoap.org/soap/encoding/’/>
</output>
</operation>
</binding>

[/sourcecode]

Partie 5 : Service

Le service, déclaré ci-dessous, est défini avec une seule occurrence du port getResultPort, ainsi que la définition de ce service. Le port est lié à la liaison (binding) getResultBinding. Enfin, on donne l’information sur l’URL du point de sortie de l’application (ici l’URL du serveur SOAP).

[sourcecode language="xml"]

<service name=’getResultService’>
<documentation>Retourne le résultat de l’opération </documentation>
<port name=’getResultPort’ binding=’getResultBinding’>
<soap:address location=’http://votre-adresse.com/samples/soap-server.php’/>
</port>
</service>

[/sourcecode]

Notez bien que si on ne trouve qu’un seul élément documentation dans notre documentation, il faudra normalement en déclarer un pour chaque élément…

L’exemple montre bien le caractère verbeux de WSDL. Cependant, il est dans la pratique assez rare d’écrire le corps du fichier à la main : la plupart des environnements de développement savent en effet générer le fichier WSDL sur la base des caractéristiques du service développé.

Bien que vous soyez certainement capable de créer un document WSDL à la main, quelques outils permettent d’automatiser le processus de définition d’un Web Service avec WSDL. Par exemple:

  • Omniopera: éditeur XSD, XML et WSDL basé sur GUI
  • SOAP Toolkit de Microsoft: boîte à outils qui inclut des assistants pour la création d’interfaces COM à partir de définitions WSDL, et pour générer du WSDL à partir d’interfaces COM
  • Zend Framework : Zend_Soap_AutoDiscover du Zend Framework est en mesure d’inspecter une classe au runtime et de générer à la volée le fichier WSDL correspondant.

Séparation et capitalisation

La facilité de maintenance est toujours au cœur des préoccupations des éditeurs. Il se révèle de ce point de vue très bénéfique de distinguer dans un contrat WSDL l’aspect Abstrait (ce qui est indépendant de la technologie et des protocoles) et l’aspect Concret (ce qui est dépendant). Cette distinction permet de joindre ou réutiliser des sous-parties de modèles WSDL et de les redéployer à loisir : le WSDL est classiquement séparable en trois parties :

  • Les schémas d’une part, qui définissent les informations contenues dans les messages reçus/émis par le service : ces schémas peuvent préexister avant la notion de service car ils représentent les entités métier
  • Une définition abstraite du service, contenant sa description sans les modalités d’implémentation (protocole et déploiement)
  • Une partie concrète qui propose les liaisons d’une interface selon un certain format avec un protocole donné à une adresse donné

Dans ce but, WSDL permet d’importer des WSDL et des schémas. La partie concrète d’un contrat WSDL peut donc importer les définitions abstraites des services qui eux même peuvent importer des schémas. Cette démarche apporte une plus grande facilité de maintenance et de lisibilité.

Trois aspects distincts d'un WSDL

Pour plus d’exemples ou de documentations, consultez :

C’est en rédigeant cet article que je me suis rendu compte qu’il y avait beaucoup de chose à dire sur la création d’un fichier WSDL. Si vous deviez retenir quelques termes de cet article les voici :

  • Le WSDL sert à décrire :
    • le protocole de communication (SOAP RPC ou SOAP orienté message)
    • le format de messages requis pour communiquer avec ce service
    • les méthodes que le client peut invoquer
    • la localisation du service
  • Une description WSDL est un document XML qui commence par la balise <definitions> et qui contient les balises suivantes :

    • <binding> : définit le protocole à utiliser pour invoquer le service web
    • <port> : spécifie l’emplacement actuel du service
    • <service> : décrit un ensemble de points finaux du réseau
  • Un WSDL est décomposé en trois parties :`

    • Schéma
    • Définition Abstraite
    • Projection Concrète

Suite à la longueur de cet article j’ai décidé de créer une troisième partie qui permettra de mettre en œuvre et déployer le Web Service. Vous trouverez également les différents fichiers à télécharger, ainsi qu’une démonstration de l’appel à la méthode getResult.

Pensez-vous qu’il faut devenir un gourou du WSDL ? Quelle est votre démarche de production des WSDL ?

  • Pingback: Ecrire un Web Service en PHP – Partie 1 – Définitions | Le blog des nouvelles technologies : Web, Technologies, Développement, Interopérabilité

  • Pingback: Ecrire un Web Service en PHP – Partie 3 – Mettre en œuvre et déployer le service, appel par un client | Le blog des nouvelles technologies : Web, Technologies, Développement, Interopérabilité

  • manu

    bonjour

    Comment faire pour sécuriser tout ça?

    d’un côté j’ai un web service opérationnel.

    De l’autre une base d’utilisateurs ayant déjà un login / pass

    Comment les lier? et surtout comment les lier de facon « sécurisante »?

    Authentification HTTP Basic + ssl ? mais comment lier tout ça à ma base?

    Merci

    • http://www.cv-developpeur-web2.com Yohann Poiron

      Bonjour Manu !

      Alors pour te répondre je te propose de revenir en fin de semaine. J’ai commencé un article j’espère le finir d’ici la fin de semaine…
      Pourras-tu attendre jusqu’à là ?

      Merci pour tes questions, très intéressantes.

  • http://dotclear.placeoweb.com/post/Generation-automatique-du-wsdl-de-definition-du-web-service-heberge-sur-un-serveur-php Placeoweb

    Ces 2 liens de générateur de WSDL sont obsolètes :
    # Omniopera
    # SOAP Toolkit de Microsoft

    • http://www.cv-developpeur-web2.com Yohann Poiron

      Hum effectivement… je vais modifier le contenu.

      Merci de votre retour.

  • cyrillus59

    bonjour, alors merci deja pour ce tuto bien fait mais dis moi une tite question me trotte si je veux ajouter une methode a mon service dois je rajouter une balise ma methode parce que je ne vois pas comment fiare la ?merci

  • http://www.cv-developpeur-web2.com Yohann Poiron

    Bonjour,

    Merci de votre commentaire.

    Effectivement pour ajouter une méthode il faut déjà la déclarer dans la partie 2 (message), puis la partie 3 (un nouvel élément dans operation dans portType) puis également dans la partie 4. Enfin, la partie 5 et l’élément service doit contenir un port.

    Ais-je été assez clair ?

  • cyrillus59

    D abord merci pour la reponse

    donc si je comprend bien le service « getresult » peut contenir plusieurs methode qui peuvent etre appelées ? apartir du moment ou elle sont declarer ? parce que dans le server-soap.php c est la fonction getresult qui est declarée…..je ne comprend pas peux tu me faire un exemple avec un server-soap contenant plusieurs web services….je suis un peu perdu la …

    merci merci ;)

    • http://www.cv-developpeur-web2.com Yohann Poiron

      Bonjour,

      Je viens de rajouter un fichier sur le serveur. Vous pouvez le télécharger à cette adresse : Plusieurs fonctions pour server-soap.

      Cela vous convient ?

      • cyrillus59

        Bonjour,

        tout d abord merci pour cette aide j y voi un peu plus clair mais pas assez pour resoudre le pb en effet le service avec plusieur me retourne une erreur que je suis imcapable de resoudre une petite aide siou plait ???

        Merci merci

        • http://www.cv-developpeur-web2.com Yohann Poiron

          Bonjour,

          Quel est l’erreur retournée ?

  • cyrillus59

    This XML file does not appear to have any style information associated with it. The document tree is shown below.

    WSDL

    SOAP-ERROR: Parsing WSDL: Missing / with name ‘sendResult’

    • http://www.cv-developpeur-web2.com Yohann Poiron

      Pouvez-vous m’envoyer votre projet compressé à l’adresse suivante : contact at blog-nouvelles-technologies.fr

      • cyrillus59

        voila qui est fait ..

        • http://www.cv-developpeur-web2.com Yohann Poiron

          Voilà qui est corrigé :)

  • Arno

    (re) Bonjour,

    Je suis plutôt d’accord avec ce que dit cyrillus59, le tuto est très bien fait, mais nommer le service (definitions name='getResult') comme la fonction principale peut porter à confusion lors de la création d’un WSDL (quand mettre le nom de la fonction? quand mettre le nom du service?)…

    En tout cas, ça m’aide bien!!!

  • Pingback: BlogInTheBox | Ecrire un Web Service en PHP – SOAP