Zend_XmlRpc_Server.xml 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!-- EN-Revision: 13868 -->
  3. <!-- Reviewed: no -->
  4. <sect1 id="zend.xmlrpc.server">
  5. <title>Zend_XmlRpc_Server</title>
  6. <sect2 id="zend.xmlrpc.server.introduction">
  7. <title>Introduction</title>
  8. <para><classname>Zend_XmlRpc_Server</classname> fournit un serveur XML-RPC qui suit les spécifications <ulink
  9. url="http://www.xmlrpc.com/spec">dictées par www.xmlrpc.com</ulink>. Il fournit aussi la méthode
  10. <code>system.multicall()</code>, permettant le traitement de requêtes multiples.</para>
  11. </sect2>
  12. <sect2 id="zend.xmlrpc.server.usage">
  13. <title>Usage de base</title>
  14. <para>Voici un exemple d'utilisation basique :</para>
  15. <programlisting role="php"><![CDATA[
  16. $server = new Zend_XmlRpc_Server();
  17. $server->setClass('My_Service_Class');
  18. echo $server->handle();
  19. ]]></programlisting>
  20. </sect2>
  21. <sect2 id="zend.xmlrpc.server.structure">
  22. <title>Structures du serveur</title>
  23. <para><classname>Zend_XmlRpc_Server</classname> se décompose en un objet serveur (lui-même), un objet requête, réponse, et
  24. des objets d'erreurs.</para>
  25. <para>Pour démarrer un serveur <classname>Zend_XmlRpc_Server</classname>, vous devez attacher une ou plusieurs classes ou
  26. fonctions au serveur, grâce à <code>setClass()</code> et <code>addFunction()</code>.</para>
  27. <para>Lorsque c'est fait, vous pouvez passer un objet <classname>Zend_XmlRpc_Request</classname> à
  28. <classname>Zend_XmlRpc_Server::handle()</classname>, sinon par défaut il utilisera un objet
  29. <classname>Zend_XmlRpc_Request_Http</classname> qui récupérera la requête depuis <code>php://input</code>.</para>
  30. <para><classname>Zend_XmlRpc_Server::handle()</classname> va alors essayer de traiter la requête. Cette méthode retournera
  31. un objet <classname>Zend_XmlRpc_Response</classname> ou <classname>Zend_XmlRpc_Server_Fault</classname>. Tous deux possèdent une
  32. méthode <code>__toString()</code> qui crée une réponse XML valide XML-RPC.</para>
  33. </sect2>
  34. <sect2 id="zend.xmlrpc.server.conventions">
  35. <title>Conventions</title>
  36. <para><classname>Zend_XmlRpc_Server</classname> permet d'attacher des classes et/ou des fonctions au serveur XML-RPC.
  37. Grâce à <classname>Zend_Server_Reflection</classname>, l'introspection va utiliser les blocs de commentaires pour
  38. déterminer les types d'arguments et de réponse de la fonction/classe.</para>
  39. <para>Les types XML-RPC n'ont pas forcément de correspondance native vers un type PHP. Le code fera de son mieux
  40. pour deviner le type de données approprié, en se basant sur les valeurs listées dans les balises @param et
  41. @return. Certains types XML-RPC n'ont par contre pas d'équivalent PHP direct, ils devront alors être spécifiés
  42. manuellement sous forme de balises phpdoc :</para>
  43. <itemizedlist>
  44. <listitem>
  45. <para>dateTime.iso8601, une chaîne formatée comme YYYYMMDDTHH:mm:ss</para>
  46. </listitem>
  47. <listitem>
  48. <para>base64, données encodées en base64</para>
  49. </listitem>
  50. <listitem>
  51. <para>struct, tableau associatif</para>
  52. </listitem>
  53. </itemizedlist>
  54. <para>Voici un exemple d'utilisation de type particulier:</para>
  55. <programlisting role="php"><![CDATA[
  56. /**
  57. * This is a sample function
  58. *
  59. * @param base64 $val1 Base64-encoded data
  60. * @param dateTime.iso8601 $val2 An ISO date
  61. * @param struct $val3 An associative array
  62. * @return struct
  63. */
  64. function myFunc($val1, $val2, $val3)
  65. {}
  66. ]]></programlisting>
  67. <para>PhpDocumentor ne vérifie (valide) pas les types des paramètres, mais les types sont obligatoires pour que
  68. le serveur puisse lui, valider les paramètres passés aux appels des méthodes.</para>
  69. <para>Il est parfaitement valide de spécifier plusieurs types pour les paramètres et les retours de méthodes. La
  70. spécification XML-RPC suggère que system.methodSignature retourne un tableau des possibilités au regard des
  71. paramètres d'entrée de la méthode, et de son type de sortie. Ceci ce fait grâce au caractère '|' de
  72. PhpDocumentor</para>
  73. <programlisting role="php"><![CDATA[
  74. /**
  75. * This is a sample function
  76. *
  77. * @param string|base64 $val1 String or base64-encoded data
  78. * @param string|dateTime.iso8601 $val2 String or an ISO date
  79. * @param array|struct $val3 Normal indexed array or an associative array
  80. * @return boolean|struct
  81. */
  82. function myFunc($val1, $val2, $val3)
  83. {}
  84. ]]></programlisting>
  85. <para>Attention toutefois, une signature multiple peut prêter à confusion au regard des personnes utilisant
  86. votre service. En général une fonction ne devrait posséder qu'une seule signature.</para>
  87. </sect2>
  88. <sect2 id="zend.xmlrpc.server.namespaces">
  89. <title>Utiliser des espaces de noms (Namespaces)</title>
  90. <para>XML-RPC accepte le concept d'espace de noms, ce qui permet de grouper les méthodes XML-RPC. Ceci aide à
  91. prévenir les collisions de noms (deux fonctions avec le même nom), de différentes classes. Par exemple le
  92. serveur XML-RPC sert des méthodes dans l'espace "system" :</para>
  93. <itemizedlist>
  94. <listitem>
  95. <para>system.listMethods</para>
  96. </listitem>
  97. <listitem>
  98. <para>system.methodHelp</para>
  99. </listitem>
  100. <listitem>
  101. <para>system.methodSignature</para>
  102. </listitem>
  103. </itemizedlist>
  104. <para>En interne la correspondance est faite avec les méthodes du même nom, de
  105. <classname>Zend_XmlRpc_Server</classname>.</para>
  106. <para>Si vous voulez ajouter un espace de noms aux méthodes que vous servez, procédez alors comme suit :</para>
  107. <programlisting role="php"><![CDATA[
  108. // Toutes les méthodes publiques de My_Service_Class seront accessibles
  109. // via myservice.METHODNAME
  110. $server->setClass('My_Service_Class', 'myservice');
  111. // la fonction 'somefunc' sera accessible via funcs.somefunc
  112. $server->addFunction('somefunc', 'funcs');
  113. ]]></programlisting>
  114. </sect2>
  115. <sect2 id="zend.xmlrpc.server.request">
  116. <title>Requêtes personnalisées</title>
  117. <para>La plupart du temps, vous utiliserez l'objet de requête par défaut <classname>Zend_XmlRpc_Request_Http</classname>,
  118. sans vous en occuper. En revanche si vous avez un besoin spécifique, comme par exemple journaliser la requête,
  119. traiter une requête CLI, GUI, ou autre environnement, vous devrez alors créer un objet étendant
  120. <classname>Zend_XmlRpc_Request</classname>. Implémentez les méthodes <code>getMethod()</code> et <code>getParams()</code>
  121. afin que le serveur puisse analyser ces informations pour traiter la requête.</para>
  122. </sect2>
  123. <sect2 id="zend.xmlrpc.server.response">
  124. <title>Réponses personnalisées</title>
  125. <para>Comme avec les objets de requête, <classname>Zend_XmlRpc_Server</classname> peut retourner des objets de réponse
  126. personnalisés. Par défaut il s'agit d'objets <classname>Zend_XmlRpc_Response_Http</classname> qui envoient un en-tête HTTP
  127. Content-Type HTTP pour XML-RPC. Vous pourriez utiliser des objets de réponse personnalisés pour par exemple
  128. renvoyer les réponses vers STDOUT, ou les journaliser.</para>
  129. <para>Pour utiliser une classe de réponse personnalisée, utilisez
  130. <classname>Zend_XmlRpc_Server::setResponseClass()</classname> avant d'appeler <code>handle()</code>.</para>
  131. </sect2>
  132. <sect2 id="zend.xmlrpc.server.fault">
  133. <title>Gérer les exceptions grâce aux erreurs (Faults)</title>
  134. <para><classname>Zend_XmlRpc_Server</classname> attrape les Exceptions générées par vos classes/fonctions, et génère une
  135. réponse XML-RPC "fault" lorsqu'une exception a été rencontrée. Par défaut, les message et code des exceptions ne
  136. sont pas attachés dans la réponse XML-RPC. Ceci est du au fait que de telles exceptions peuvent en dire trop, au
  137. regard de la sécurité de votre application.</para>
  138. <para>Des classes d'exception peuvent cependant être mises en liste blanche, et donc utilisées pour les réponses
  139. d'erreur ("fault"). Utilisez simplement <classname>Zend_XmlRpc_Server_Fault::attachFaultException()</classname> en lui
  140. passant une classe d'exception :</para>
  141. <programlisting role="php"><![CDATA[
  142. Zend_XmlRpc_Server_Fault::attachFaultException('My_Project_Exception');
  143. ]]></programlisting>
  144. <para>Si vous héritez correctement vos exceptions, vous pouvez alors passer en liste blanche l'exception de plus
  145. bas niveau, et ainsi accepter plusieurs types d'exceptions qui en hériteront. Évidemment, les
  146. Zend_XmlRpc_Server_Exceptions sont elles automatiquement mises en liste blanche, afin de pouvoir traiter les
  147. requêtes vers des méthodes inexistantes, ou toute autre erreur "générique".</para>
  148. <para>Toute exception rencontrée, mais non mise en liste blanche, donnera naissance à une réponse d'erreur avec
  149. le code "404" et le message "Unknown error".</para>
  150. </sect2>
  151. <sect2 id="zend.xmlrpc.server.caching">
  152. <title>Cacher la définition du serveur entre les requêtes</title>
  153. <para>Attacher beaucoup de classes au serveur XML-RPC peut consommer beaucoup de ressources, car l'introspection
  154. de chaque classe/fonction est mise en place.</para>
  155. <para>Pour améliorer les performances, <classname>Zend_XmlRpc_Server_Cache</classname> peut être utilisé pour mettre en
  156. cache la définition d'un serveur. Combiné à <code>__autoload()</code>, ceci améliore grandement les
  157. performances.</para>
  158. <para>Un exemple d'utilisation :</para>
  159. <programlisting role="php"><![CDATA[
  160. function __autoload($class)
  161. {
  162. Zend_Loader::loadClass($class);
  163. }
  164. $cacheFile = dirname(__FILE__) . '/xmlrpc.cache';
  165. $server = new Zend_XmlRpc_Server();
  166. if (!Zend_XmlRpc_Server_Cache::get($cacheFile, $server)) {
  167. require_once 'My/Services/Glue.php';
  168. require_once 'My/Services/Paste.php';
  169. require_once 'My/Services/Tape.php';
  170. $server->setClass('My_Services_Glue', 'glue');
  171. // espace de noms glue
  172. $server->setClass('My_Services_Paste', 'paste');
  173. // espace de noms paste
  174. $server->setClass('My_Services_Tape', 'tape');
  175. // espace de noms tape
  176. Zend_XmlRpc_Server_Cache::save($cacheFile, $server);
  177. }
  178. echo $server->handle();
  179. ]]></programlisting>
  180. <para>L'exemple ci dessus essaye de récupérer la définition du serveur via le fichier
  181. <filename>xmlrpc.cache</filename>. Si ceci échoue, alors les classes nécessaires au service sont chargées,
  182. attachées au serveur, et une tentative de création de cache est lancée.</para>
  183. </sect2>
  184. <sect2 id="zend.xmlrpc.server.use">
  185. <title>Exemples d'utilisation</title>
  186. <para>Voici quelques exemples qui démontrent les diverses options disponibles pour un serveur XML-RPC.</para>
  187. <sect3 id="zend.xmlrpc.server.use.case1">
  188. <title>Utilisation basique</title>
  189. <para>L'exemple ci dessous attache une fonction au service XML-RPC.</para>
  190. <programlisting role="php"><![CDATA[
  191. /**
  192. * Retourne le hash MD5 d'une valeur
  193. *
  194. * @param string $value Valeur à hasher
  195. * @return string Hash MD5 de la valeur
  196. */
  197. function md5Value($value)
  198. {
  199. return md5($value);
  200. }
  201. $server = new Zend_XmlRpc_Server();
  202. $server->addFunction('md5Value');
  203. echo $server->handle();
  204. ]]></programlisting>
  205. </sect3>
  206. <sect3 id="zend.xmlrpc.server.use.case2">
  207. <title>Attacher une classe</title>
  208. <para>L'exemple ci dessous montre comment attacher les méthodes publiques d'une classe en tant que méthodes
  209. XML-RPC.</para>
  210. <programlisting role="php"><![CDATA[
  211. $server = new Zend_XmlRpc_Server();
  212. $server->setClass('Services_Comb');
  213. echo $server->handle();
  214. ]]></programlisting>
  215. </sect3>
  216. <sect3 id="zend.xmlrpc.server.use.case3">
  217. <title>Attacher plusieurs classes grâce aux espaces de noms</title>
  218. <para>L'exemple ci dessous montre comment attacher plusieurs classes grâce aux espaces de noms.</para>
  219. <programlisting role="php"><![CDATA[
  220. require_once 'Services/Comb.php';
  221. require_once 'Services/Brush.php';
  222. require_once 'Services/Pick.php';
  223. $server = new Zend_XmlRpc_Server();
  224. $server->setClass('Services_Comb', 'comb');
  225. // méthodes appelées sous la forme comb.*
  226. $server->setClass('Services_Brush', 'brush');
  227. // méthodes appelées sous la forme brush.*
  228. $server->setClass('Services_Pick', 'pick');
  229. // méthodes appelées sous la forme pick.*
  230. echo $server->handle();
  231. ]]></programlisting>
  232. </sect3>
  233. <sect3 id="zend.xmlrpc.server.use.case4">
  234. <title>Spécifier les exceptions à utiliser en cas d'erreurs dans les réponses XML-RPC</title>
  235. <para>L'exemple ci dessous montre comment spécifier les exceptions à utiliser en cas d'erreurs dans les
  236. réponses XML-RPC.</para>
  237. <programlisting role="php"><![CDATA[
  238. require_once 'Services/Exception.php';
  239. require_once 'Services/Comb.php';
  240. require_once 'Services/Brush.php';
  241. require_once 'Services/Pick.php';
  242. // Utilise les Services_Exception pour les erreurs
  243. Zend_XmlRpc_Server_Fault::attachFaultException('Services_Exception');
  244. $server = new Zend_XmlRpc_Server();
  245. $server->setClass('Services_Comb', 'comb');
  246. // méthodes appelées sous la forme comb.*
  247. $server->setClass('Services_Brush', 'brush');
  248. // méthodes appelées sous la forme brush.*
  249. $server->setClass('Services_Pick', 'pick');
  250. // méthodes appelées sous la forme pick.*
  251. echo $server->handle();
  252. ]]></programlisting>
  253. </sect3>
  254. <sect3 id="zend.xmlrpc.server.use.case5">
  255. <title>Utiliser un objet de requête personnalisé</title>
  256. <para>L'exemple suivant montre comment utiliser un objet de requête personnalisé.</para>
  257. <programlisting role="php"><![CDATA[
  258. require_once 'Services/Request.php';
  259. require_once 'Services/Exception.php';
  260. require_once 'Services/Comb.php';
  261. require_once 'Services/Brush.php';
  262. require_once 'Services/Pick.php';
  263. // Utilise les Services_Exception pour les erreurs
  264. Zend_XmlRpc_Server_Fault::attachFaultException('Services_Exception');
  265. $server = new Zend_XmlRpc_Server();
  266. $server->setClass('Services_Comb', 'comb');
  267. // méthodes appelées sous la forme comb.*
  268. $server->setClass('Services_Brush', 'brush');
  269. // méthodes appelées sous la forme brush.*
  270. $server->setClass('Services_Pick', 'pick');
  271. // méthodes appelées sous la forme pick.*
  272. // Crée un objet de requête
  273. $request = new Services_Request();
  274. echo $server->handle($request);
  275. ]]></programlisting>
  276. </sect3>
  277. <sect3 id="zend.xmlrpc.server.use.case6">
  278. <title>Utiliser un objet de réponse personnalisé</title>
  279. <para>L'exemple suivant montre comment utiliser un objet de réponse personnalisé.</para>
  280. <programlisting role="php"><![CDATA[
  281. require_once 'Services/Request.php';
  282. require_once 'Services/Response.php';
  283. require_once 'Services/Exception.php';
  284. require_once 'Services/Comb.php';
  285. require_once 'Services/Brush.php';
  286. require_once 'Services/Pick.php';
  287. // Utilise les Services_Exception pour les erreurs
  288. Zend_XmlRpc_Server_Fault::attachFaultException('Services_Exception');
  289. $server = new Zend_XmlRpc_Server();
  290. $server->setClass('Services_Comb', 'comb');
  291. // méthodes appelées sous la forme comb.*
  292. $server->setClass('Services_Brush', 'brush');
  293. // méthodes appelées sous la forme brush.*
  294. $server->setClass('Services_Pick', 'pick');
  295. // méthodes appelées sous la forme pick.*
  296. // Crée un objet de requête
  297. $request = new Services_Request();
  298. // Utilise une réponse personnalisée
  299. $server->setResponseClass('Services_Response');
  300. echo $server->handle($request);
  301. ]]></programlisting>
  302. </sect3>
  303. <sect3 id="zend.xmlrpc.server.use.case7">
  304. <title>Cache entre les requêtes</title>
  305. <para>Les exemples suivants montrent comment gérer une politique de cache inter-requêtes.</para>
  306. <programlisting role="php"><![CDATA[
  307. require_once 'Services/Request.php';
  308. require_once 'Services/Response.php';
  309. require_once 'Services/Exception.php';
  310. require_once 'Services/Comb.php';
  311. require_once 'Services/Brush.php';
  312. require_once 'Services/Pick.php';
  313. // Specifier un fichier de cache
  314. $cacheFile = dirname(__FILE__) . '/xmlrpc.cache';
  315. // Utilise les Services_Exception pour les erreurs
  316. Zend_XmlRpc_Server_Fault::attachFaultException('Services_Exception');
  317. $server = new Zend_XmlRpc_Server();
  318. // Essaye de récupérer la définition du serveur via le cache
  319. if (!Zend_XmlRpc_Server_Cache::get($cacheFile, $server)) {
  320. $server->setClass('Services_Comb', 'comb');
  321. // méthodes appelées sous la forme comb.*
  322. $server->setClass('Services_Brush', 'brush');
  323. // méthodes appelées sous la forme brush.*
  324. $server->setClass('Services_Pick', 'pick');
  325. // méthodes appelées sous la forme pick.*
  326. // Sauve le cache
  327. Zend_XmlRpc_Server_Cache::save($cacheFile, $server));
  328. }
  329. // Crée un objet de requête
  330. $request = new Services_Request();
  331. // Utilise une réponse personnalisée
  332. $server->setResponseClass('Services_Response');
  333. echo $server->handle($request);
  334. ]]></programlisting>
  335. </sect3>
  336. </sect2>
  337. </sect1>