Zend_XmlRpc_Server.xml 18 KB

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