− Table des matières
Jelix propose via le module jsoap la prise en charge de SOAP, qui est un protocole de service web normalisé par le W3C. Jelix utilise l'API SOAP incluse dans php, donc vous devez vous assurer qu'elle est bien activée sur votre serveur (vérifiez par un phpinfo() par exemple).
Cependant, l'avantage d'utiliser Jelix pour faire du soap, est que vous n'avez
nullement besoin d'apprendre l'API SOAP, ni de manipuler le contenu XML des
messages SOAP : les paramètres soap sont interprétés et disponibles via la
méthode param()
de vos contrôleurs, et pour renvoyer vos données, vous
avez juste à indiquer une valeur PHP à l'objet réponse SOAP de jelix.
Jelix s'occupe aussi de générer le contenu WSDL automatiquement.
Il va vous falloir tout de même installer le module jsoap, et suivre une syntaxe assez précise (mais trés simple) dans les commentaires de chaque méthode de vos contrôleurs SOAP.
Installation et activation du module jsoap ¶
Comme vous le remarquez dans le point d'entrée, des classes du module jsoap sont utilisées. Vous devez donc l'installer et l'activer.
Pour l'installer, ajouter dans votre composer.json la dépendance au paquet
jelix/soap-server-module
:
composer require "jelix/soap-server-module"
Ensuite configurez le module et lancez l'installateur :
php dev.php module:configure jsoap
php install/installer.php
(Pour plus d'information : Installer un module)
Ce module inclus également tout ce qu'il faut pour faire du WSDL (voir plus bas).
Une requête SOAP est spécifique, et pour y répondre, on ne peut pas utiliser
l'objet request "classic". C'est pourquoi le module
installe un point d'entrée spécifique dans le répertoire www/
, soap.php
,
qui utilise jSOAPRequest
plutôt que jClassicRequest
, et un
objet coordinateur jSoapCoordinator
. Le type de requête et du point
d'entrée est donc "soap".
Contrôleur ¶
Comme on a affaire à un type de requête particulier, le nom du fichier du
contrôleur doit avoir le suffixe ".soap.php". Par exemple, un contrôleur
"default" : default.soap.php
. (Vous pouvez bien sûr avoir un autre
contrôleur "default" pour d'autres types de requêtes, "default.classic.php" par
exemple).
Méthode d'un contrôleur ¶
Ensuite, le contenu du contrôleur est similaire à ce que vous avez l'habitude de
faire, à la seule différence que vous utiliserez jResponseSoap
, qui a pour
alias "soap", pour répondre aux requêtes Soap :
class defaultCtrl extends jController {
/**
* Test with a simple parameter
* @externalparam string $name
* @return string
*/
function hello() {
$rep = $this->getResponse('soap');
$rep->data = "Hello ".$this->param('name');
return $rep;
}
}
Chaque action du contrôleur, donc chaque méthode du contrôleur, sera une méthode SOAP qu'il faudra indiquer au niveau des clients SOAP (voir section suivante).
Déclarer les types des paramètres et de la valeur de retour ¶
Une méthode "SOAP" a des paramètres et reçoit une valeur en retour. Il faut indiquer leur type à Jelix afin que les messages SOAP et WSDL soient générés correctement.
Pour cela, vous devez ajouter un commentaire "à la phpdoc", pour indiquer les types de paramètres soap et le type de la donnée soap en retour, afin que SOAP puisse fonctionner. C'est la seule "originalité" par rapport aux autres types de contrôleurs.
Pour indiquer les paramètres SOAP auxquels s'attend la méthode, il faut ajouter des tags "@externalparam", avec lesquels on indique le type de paramètre, et le nom du paramètre. Pour indiquer le type de la valeur de retour, il faut utiliser le mot clé "@return" suivit du type.
Les types par défaut que l'on peut indiquer sont les suivants : string, integer, int, boolean, float.
Si on veut utiliser un tableau, on ajoutera []
:
@externalparam string[] $tableau_de_chaine
S'l s'agit d'un tableau associatif, on utilisera [=>]
:
@externalparam string[=>] $tableau_de_chaine_associatif
On peut faire ça avec tous les types.
Types personnalisés ¶
Vous pouvez aussi utiliser vos propres types, c'est à dire vos propres objets
(faire l'équivalent des complextype en XMLSchema). La déclaration de vos
classes doit être incluse dans le fichier du contrôleur, soit directement, soit
via un include
.
Imaginons notre propre type MyTestStruct :
/**
* Struct used for tests
*/
class MyTestStruct{
/**
* @var string
*/
public $name = 'Dupont';
/**
* @var string
*/
public $firstName = 'Bertrand';
/**
* @var string
*/
public $city = 'Paris';
}
Notez l'usage du mot clé @var pour indiquer le type de chaque propriété. Chaque propriété devrait être commentée de cette manière.
Ensuite, au niveau du contrôleur, on n'oublie pas d'indiquer MyTestStruct
pour les paramètres et/ou la valeur de retour qui sont de ce type :
/**
* on reçoit un objet et on retourne un objet
* @externalparam MyTestStruct $input
* @return MyTestStruct
*/
function receiveObject() {
$rep = $this->getResponse('soap');
$input = $this->param('input');
$input->name = 'Name updated';
$rep->data = $input;
return $rep;
}
Bien sûr, MyTestStruct
peut avoir des propriétés qui sont elles aussi des
objets, du moment qu'on indique leur type :
/**
* An other struct used for test, this one have an other object as member propertie
*/
class MyTestStructBis{
/**
* @var MyTestStruct
*/
public $test;
/**
* @var string
*/
public $msg = 'hello';
function __construct(){
$this->test = new MyTestStruct();
}
}
Mettre en place un service WSDL ¶
Bien entendu, qui dit SOAP, dit un service WSDL qui va permettre aux clients SOAP d'être renseignés sur les services web SOAP disponibles dans votre application et comment valider les paramètres et valeurs de retour.
Pour cela, le module jsoap inclus tout ce qu'il faut. Il contient
un contrôleur nommé WSDL et possède une méthode wsdl()
. Aussi, pour
interroger le WSDL, il suffit d'indiquer à votre client SOAP une URL du genre
http://monsite.com/index.php/jsoap/WSDL/wsdl?service=unModule~unControleur
Notez qu'il faut donner un paramètre de nom "service", dans lequel on met le nom du module et le nom du contrôleur qui implémente les services SOAP (on n'indique pas de nom de méthode, juste le nom du contrôleur). En retour, un fichier WSDL est fourni, expliquant l'API proposé par ce contrôleur. Vous pouvez bien sûr avoir plusieurs contrôleurs SOAP dans votre application. Cependant, il n'y a pas de moyen pour renvoyer automatiquement un fichier WSDL qui déclarerait les services SOAP de toute votre application.
Remarque : ce type d'url est disgracieux, et vous pouvez parfaitement configurer les urls pour avoir des choses plus simple comme
http://monsite.com/index/jsoap/unModule/unControleur
Notez que vous pouvez afficher une version HTML de la liste des services SOAP, en appelant la méthode "index" du contrôleur WSDL.
http://monsite.com/index.php/jsoap/WSDL/index?service=unModule~unControleur
Appel depuis un client SOAP ¶
Qui dit SOAP, dit une partie cliente qui envoie une requête en SOAP. Cela peut être un script JS qui le fait, mais aussi une autre application PHP. Voici un exemple en PHP utilisant l'extension SOAP :
ini_set('soap.wsdl_cache_enabled', 0);
// Client utilisant l'extension soap pour faire appel au serveur soap Jelix
// Chargement du WSDL
try {
$wsdlURI = "http://monsite.com/index.php/jsoap/WSDL/wsdl?service=myapp~default";
$client = new SoapClient($wsdlURI, array('trace' => 1, 'soap_version' => SOAP_1_1));
} catch (SoapFault $fault) {
throw new Exception($fault->getMessage());
}
try {
$result = $client->__soapCall('hello', array('Sylvain'));
//...
$result = $client->__soapCall('returnObjects', array());
//...
$result = $client->__soapCall('returnObjectBis', array());
// ...
} catch (SoapFault $fault) {
print_r($fault);
throw new Exception($fault->getMessage());
}
Appeler un service SOAP avec Jelix ¶
Si votre application Jelix a besoin d'appeler un serveur soap, vous pouvez
utiliser jSoapClient
. C'est une classe qui renvoi un objet
SoapClient
préconfiguré avec les paramètres stockés dans un profil de
connexion, donc dans var/config/profiles.ini.php
, comme pour jDb.
Pour l'utiliser, ajouter une section [jsoapclient]
contenant les alias de
profils, et autant de section [jsoapclient:xxx]
que vous avez de services
SOAP à appeler (une par WSDL en fait). "xxx" étant le nom d'un profile que vous
donnerez librement. L'alias default
indiquant le profile par défaut.
Un profil doit contenir au moins une option wsdl
, contenant l'URL d'un
fichier WSDL. Vous pouvez ajouter d'autres paramètres correspondant à des
options pour la classe SoapClient.
[jsoapclient]
[jsoapclient:default]
wsdl= "http://example.com/books.wsdl"
soap_version = SOAP_1_1
Et dans votre code :
$client = jSoapClient::get(); // indiquer un nom de profile si ce n'est pas celui par défaut
$result = $client->hello('Sylvain');
// ou
$result = $client->__soapCall('hello', array('Sylvain'));
Vous pouvez indiquer une option classmap dans le profil, pour mapper des classes sur des types soap. Vous devez utiliser le format json pour indiquer ce mapping.
[jsoapclient:default]
wsdl= "http://example.com/books.wsdl"
soap_version = SOAP_1_1
classmap = '{"soaptype":"myclass", "soaptype2":"myclass2"}'
Les classes que vous indiquez doivent être déjà chargée avec l'appel à jSoapClient::get()
.
Vous pouvez aussi déclarer ce mapping dans un fichier
ini séparé, et d'indiquer ce fichier dans une propriété classmap_file
. Ce fichier doit
se trouver dans le répertoire votreappli/app/system/
.
[jsoapclient:default]
wsdl= "http://example.com/books.wsdl"
soap_version = SOAP_1_1
classmap_file = soap_classmap.ini.php
Et dans ce fichier ini, il y a autant de sections que de profils jsoapclient, avec les mêmes noms (sans le prefixe "jsoapclient:"). À l'intérieur des sections, il y a une liste de "cle=valeur". Les clés sont les noms des types soap, et les valeurs les noms des classes PHP.
[default]
soaptype=myclass
soaptype2=myclass2
Vous pouvez aussi avoir une section __common__
qui déclare un mapping pour tous les profils.
Le mapping pour un profil donné, contiendra le mapping de __common__
, celui de la section correspondante
dans le fichier de mapping, et éventuellement celui déclaré dans la propriété classmap
du profil.
Autre options de configurations :
trace=on
: pour activer le deboggage. Dans un fichier de log de type "soap", vous aurez les requetes et réponses soap. Configurez correctement le logger, par exemple :
[logger]
soap=file
[fileLogger]
soap=soap.log
Depuis Jelix 1.6.16, vous pouvez aussi utiliser le logger soapfile
au lieu
de file
, qui crée un fichier XML pour chaque requete et réponse XML des
appels SOAP, permettant un debuggage plus aisé.
exceptions
: c'est un booléen définissant si les erreurs SOAP doivent lancer des exceptions du type SoapFault.connection_timeout
: temps d'attentes d'une réponse avant d'émettre une erreurssl_self_signed
(depuis 1.6.15) : si à "on", il n'y a pas de vérification du certificat SSL pour les serveurs SOAP en https. À ne pas activer pour les serveurs non locaux.