Interopérabilité PHP / C# via WebService

Jérémie Bertrand

Nous allons voir dans cet article ce qu'est un fichier WSDL, suivi par la création d'un WebService en PHP consommé par une application .NET en C# et l'inverse, la création d'un WebService C# (en WCF) consommé par une application PHP.

Commentez

- Titre : Interopérabilité PHP / C# via WebService

- Auteur : Jérémie Bertrand

- Parution : 15 novembre 2009

- Mise à jour : 4 mars 2010

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2009 Jérémie Bertrand. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts. Droits de diffusion permanents accordés à Developpez LLC.

Sommaire

- I. Introduction

- II. Le fichier WSDL

- III. WebService PHP consommé par une application C#

- IV. WebService C# en WCF consommé par une application PHP

- V. Conclusion

- VI. Remerciements

- VII. Contact

I - Introduction

Interopérabilité est peut-être un bien grand mot pour décrire ce qui va suivre. En effet, dès que l'on parle de WebService, il suffit d'avoir un fichier WSDL pour qu'on puisse consommer le WebService par une application d'un autre langage. Nous verrons donc dans un premier temps ce qu'est un fichier WSDL, puis la création d'un WebService en PHP consommé par une application .NET en C# et inversement.

II - Le fichier WSDL

Nous verrons juste une rapide présentation, pour plus d'information, vous pouvez aller voir ici (http://www.w3.org/TR/wsdl).

Le fichier WSDL décrit une Interface publique d'accès à un Service Web, notamment dans le cadre d'architectures de type SOA (Service Oriented Architecture). C'est une description fondée sur le XML qui indique « comment communiquer pour utiliser le service ». Il décrit notamment le Protocole de communication (SOAP RPC ou SOAP orienté message), le format de messages requis pour communiquer avec le service, les méthodes que le client peut invoquer ainsi que la localisation du service. Le fichier WSDL est un fichier 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

Les opérations possibles et les messages sont décrits de façon abstraite mais cette description renvoie à des protocoles réseaux et formats de messages concrets.

Il y a différents moyens de réaliser ce fichier, certains seront décrits dans cet article, mais étant donné que c'est du XML, un simple bloc note suffit !

III - WebService PHP consommé par une application C#

Pour créer un WebService facilement en PHP, il faut utiliser PHP5 avec l'extension SOAP d'activée. Pour cela, le mieux est de travailler en local avec Wamp Server (Wamp 5), qui permet d'activer cette extension.

Une fois le matériel prêt, on va commencer par ouvrir notre éditeur PHP préféré et écrire la classe qui va être utilisée par le WebService.

Dans notre exemple, on va juste définir une petite classe chargée de faire une opération et une soustraction :

PHP

class Math
{
public function Add($a, $b)
{
return $a + $b;
}

public function Substract($a, $b)
{
return $a - $b;
}
}

Voilà donc les méthodes qui seront exposées par le WebService.

Il ne reste plus qu'à créer le serveur et la partie PHP sera terminée. Pour cela, nous allons utiliser la classe SoapServer :

PHP

require 'Math.class.php';

// première étape : désactiver le cache wsdl lors de la phase de test
ini_set("soap.wsdl_cache_enabled", "0");

$wsdl    = 'WebService.wsdl';
//Création du serveur SOAP avec le fichier WSDL
$server = new SoapServer($wsdl);
//Ajout de la classe Math dans les éléments proposés par le WebService
$server->setClass('Math');

//l'utilisation du WebService se fera toujours par la méthode POST
if ($_SERVER["REQUEST_METHOD"] == "POST")
{
$server->handle();
}
else //dans le cas contraire, la page affichera les méthodes proposées par le WebService
{
echo '<h4>Ce serveur SOAP peut gérer les fonctions suivantes : </h4><ul>';
$functions = $server->getFunctions();
foreach($functions as $func)
{
echo '<li>'.$func.'</li>';
}

echo '</ul>';
}

Vous avez sûrement remarqué qu'on fait appel au fichier WebService.wsdl alors qu'on ne l'a pas encore créé. On va donc s'en charger maintenant. Le mieux pour cela est d'utiliser un logiciel qui va générer le fichier wsdl final grâce à des informations qu'on lui aura apporté. Pour ma part j'utilise Altova XML Spy qui est disponible gratuitement en version d'essai. Voilà donc ce que ça donne en version graphique :

La partie serveur est à présent terminée, attaquons-nous au client .net en C#.

L'utilisation de Visual Studio 2008 est conseillée, il permet la génération automatique d'un proxy grâce à WCF qui va travailler à partir du fichier WSDL.

On va commencer par créer une application console. Ensuite, il suffit d'ajouter un Service Reference en passant comme adresse celle du fichier WSDL (http://localhost/WebServices/WebService.wsdl dans notre cas) et Math comme namespace pour la référence.

WCF a alors généré la classe MathServiceClient ainsi qu'un fichier de configuration qui vont nous servir à interagir avec le WebService.

On va tout d'abord instancier cette classe :

C#

MathServiceClient math = new MathServiceClient();

Puis on va simplement appeler nos deux méthodes :

C#

Console.WriteLine(math.Add(5, 5));
Console.WriteLine(math.Substract(10, 5));

Et bien sûr, il ne faut pas oublier de fermer le client :

C#

math.Close();

Et voilà, notre client .net consomme notre WebService PHP !

IV - WebService C# en WCF consommé par une application PHP

Je ne vais pas détailler WCF ici, nous allons juste voir la mise en place d'un service via une application console. Si vous souhaitez en savoir plus sur WCF, voilà l'excellent article de Julien Corioland. (http://blogs.dotnet-france.com/julienc/post/Introduction-a-Windows-Communication-Foundation.aspx)

Pour faire rapide, pour un service WCF il est préférable d'avoir 3 projets différents : une bibliothèque de classes qui contiendra une interface qui servira de « contrat » pour le service, une bibliothèque de classe qui contiendra une classe qui implémentera le « contrat », et dans le cas présent, une application console qui va servir de serveur et qui va donc exposer le service.

Le service exposera les mêmes méthodes que dans le post précédent, c'est-à-dire une addition et une soustraction d'entiers.

Après avoir créé une première bibliothèque de classe nommée ServiceContract par exemple, il faut définir l'interface du service :

C#

[ServiceContract]
public interface IService
{
[OperationContract]
public int Add(int a, int b);

[OperationContract]
public int Substract(int a, int b);
}

L'attribut ServiceContract définit le contrat du service qui sera exposé. Il possède une propriété Namespace qui permet de changer le namespace du service (tempuri.org par défaut).

L'attribut OperationContract définit les méthodes visibles du service.

Ensuite, il faut créer la deuxième bibliothèque de classes qui va contenir l'implémentation du service :

C#

public class Math : IService
{
#region IService Members

public int Add(int a, int b)
{
return a + b;
}

public int Substract(int a, int b)
{
return a - b;
}

#endregion
}

Jusque là, rien de bien compliqué, il suffit d'implémenter l'interface définie plus haut. Passons maintenant au serveur, qui exposera le service WCF.

Le serveur sera une application console des plus classiques. La première chose à faire est de créer un fichier de configuration (App.config) qui va paramétrer le type, l'adresse et le protocole du service.

XML

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>

<services>
<!-- le type du service  -->
<service name="ServiceImplementation.Math">
<host>
<baseAddresses>
<!-- l'adresse où le service sera accessible  -->
<add baseAddress="http://localhost:1664/MathService"/>
</baseAddresses>
</host>
<!-- le protocole pour joindre le service  -->
<endpoint address=""
binding="basicHttpBinding"
contract="ServiceContract.IMathService" />
</service>
</services>

</system.serviceModel>
</configuration>

On crée ensuite un host en lui indiquant le type que l'on veut exposer en service :

C#

ServiceHost host = new ServiceHost(typeof(ServiceImplementation.Math));

Il suffit ensuite de mettre le service en écoute :

C#

host.Open();

Console.WriteLine("Le service Math est à l'écoute");

Console.WriteLine("Appuyez sur une touche pour quitter");

Console.ReadLine();
host.Close();

Le service est maintenant prêt.

Mais le fichier WSDL n'a pas été créé, ce qui manque cruellement pour pouvoir consommer le service avec une application PHP. Heureusement, WCF permet de le générer automatiquement. Pour cela, il suffit de modifier le fichier de configuration.

On va tout d'abord rajouter un comportement au service. Dans la balise System.ServiceModel, on rajoute ceci :

XML

<behaviors>
<serviceBehaviors>
<behavior name="MathServiceBehaviors" >
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>

Il faut ensuite modifier la balise service comme suit :

XML

<service name="ServiceImplementation.Math" behaviorConfiguration="MathServiceBehaviors">

Et voilà, notre service peut maintenant être consommé par n'importe quelle application via son fichier WSDL.

Il ne reste plus qu'à faire le client PHP. Pour cela, le mieux est de générer le client SOAP à partir du fichier WSDL. Je me suis personnellement servi de wsdl2php, disponible ici : http://www.urdalen.no/wsdl2php/, mais d'autres scripts font ça très bien aussi, comme WSDLInterpreter : http://code.google.com/p/wsdl2php-interpreter/.

Une fois le WSDL passé à la moulinette, on obtient donc une jolie classe Math qui hérite de SoapClient et qui possède deux fonctions : Add et Substract.

D'autres classes de deux types différents sont également générées :

- les classes qui vont servir à passer les paramètres : Add qui contient les deux entiers pour faire l'addition et Substract qui contient également deux entiers pour la soustraction.

- les classes qui vont contenir la réponse du WebService : AddResponse qui possède une propriété AddResult qui est le résultat de l'addition, et SubsctractResponse qui possède une propriété SubstractResult qui est le résultat de la soustraction.

Toutes ces classes sont générées dans un seul fichier au nom du service : Math.php.

Maintenant qu'on a de quoi consommer le service WCF, il ne reste plus qu'à faire le client PHP. On va tout d'abord créer le fichier client.php. Première chose à ajouter, un include sur le fichier généré par wsdl2php : Math.php.

Ensuite, on va instancier le client du service Math :

PHP

$client = new Math();

Il faut maintenant créer les paramètres pour la fonction Add :

PHP

$addParameters = new Add();
$addParameters->a = 2;
$addParameters->b = 2;

Vous remarquerez que a et b correspondent aux noms des paramètres de la fonction Add définis par le contrat du service.

On appelle la fonction Add :

PHP

$result = $client->Add($addParameters);

On peut ensuite utiliser la propriété AddResult de $result pour récupérer le résultat de l'addition et l'afficher par exemple :

PHP

echo $result->AddResult;

Et c'est fini, nous avons maintenant un client PHP qui consomme notre service WCF !

V - Conclusion

Vous savez maintenant comment créer et utiliser un client et un serveur en PHP et en WCF afin de faire communiquer vos applications.

Les sources de cet article sont disponibles ici (Miroir).

VI - Remerciements

Je remercie mlny84 et shawn12 pour leur relecture ainsi que RideKick et tomlev pour leurs conseils et remarques.

VII - Contact

Vous pouvez me contacter par message privé pour toute remarque ou suggestion.