Zend_XmlRpc_Client.xml 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!-- EN-Revision: 13825 -->
  3. <!-- Reviewed: no -->
  4. <sect1 id="zend.xmlrpc.client">
  5. <title>Zend_XmlRpc_Client</title>
  6. <sect2 id="zend.xmlrpc.client.introduction">
  7. <title>Introduction</title>
  8. <para>Zend Framework possède la capacité de consommer des services distants XML-RPC, via la classe
  9. <classname>Zend_XmlRpc_Client</classname>. Ses caractéristiques principales sont la conversion automatique des types entre
  10. PHP et XML-RPC, un objet proxy de serveur, et des possibilités d'introspection du serveur.</para>
  11. </sect2>
  12. <sect2 id="zend.xmlrpc.client.method-calls">
  13. <title>Appels de méthodes</title>
  14. <para>Le constructeur de <classname>Zend_XmlRpc_Client</classname> reçoit en premier paramètre l'URL du serveur XML-RPC
  15. distant. L'instance retournée pourra alors être utilisée pour appeler n'importe quelle méthode distante.</para>
  16. <para>Pour appeler une méthode distante, utilisez la méthode <code>call()</code> de votre instance. Le code
  17. suivant montre un exemple avec le serveur XML-RPC du site de Zend Framework. Vous pouvez l'utiliser pour tester
  18. ou explorer les possibilités des composants <classname>Zend_XmlRpc</classname>.</para>
  19. <example id="zend.xmlrpc.client.method-calls.example-1">
  20. <title>XML-RPC appel de méthode</title>
  21. <programlisting role="php"><![CDATA[
  22. $client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
  23. echo $client->call('test.sayHello');
  24. // hello
  25. ]]></programlisting>
  26. </example>
  27. <para>Le type de la valeur XML-RPC retournée sera automatiquement casté en un type compatible PHP. Dans
  28. l'exemple ci-dessus, une <code>string</code> PHP est retournée et immédiatement utilisable.</para>
  29. <para>Le premier paramètre de <code>call()</code> est le nom de la méthode distante à appeler. Si celle-ci
  30. demande des paramètres, ceux-ci doivent alors être passés via le deuxième paramètre de <code>call()</code>, sous
  31. forme de tableau PHP (<code>array</code>) :</para>
  32. <example id="zend.xmlrpc.client.method-calls.example-2">
  33. <title>XML-RPC appel de méthode avec des paramètres</title>
  34. <programlisting role="php"><![CDATA[
  35. $client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
  36. $arg1 = 1.1;
  37. $arg2 = 'foo';
  38. $result = $client->call('test.sayHello', array($arg1, $arg2));
  39. // $result est un type PHP natif
  40. ]]></programlisting>
  41. </example>
  42. <para>Le tableau de paramètres peut contenir des types PHP natifs, des objets <classname>Zend_XmlRpc_Value</classname>, ou
  43. bien les deux à la fois.</para>
  44. <para>La méthode <code>call()</code> convertira automatiquement la réponse XML-RPC et retournera un type PHP
  45. natif valide. Un objet <classname>Zend_XmlRpc_Response</classname> pour la valeur de retour sera de même disponible, via
  46. un appel à <code>getLastResponse()</code>.</para>
  47. </sect2>
  48. <sect2 id="zend.xmlrpc.value.parameters">
  49. <title>Types et conversions</title>
  50. <para>Certaines méthodes distantes requièrent des paramètres. Ceux-ci sont donnés sous forme de tableau PHP à
  51. <code>call()</code>. Chaque paramètre est supposé être un type PHP natif qui sera alors lui-même converti, ou
  52. alors un objet représentant un type XML-RPC (un objet parmi les <classname>Zend_XmlRpc_Value</classname>).</para>
  53. <sect3 id="zend.xmlrpc.value.parameters.php-native">
  54. <title>Types PHP natifs comme paramètres</title>
  55. <para>Les paramètres passés à <code>call()</code> peuvent être d'un type PHP natif, à savoir
  56. <code>string</code>, <code>integer</code>, <code>float</code>, <code>boolean</code>, <code>array</code>, ou
  57. <code>object</code>. Dans ce cas, chacun des types sera converti de manière automatique en son type
  58. compatible XML-RPC, suivant la table suivante :</para>
  59. <table id="zend.xmlrpc.value.parameters.php-native.table-1">
  60. <title>PHP et XML-RPC, conversions de types</title>
  61. <tgroup cols="2">
  62. <thead>
  63. <row>
  64. <entry>Type PHP natif</entry>
  65. <entry>XML-RPC type</entry>
  66. </row>
  67. </thead>
  68. <tbody>
  69. <row>
  70. <entry>integer</entry>
  71. <entry>int</entry>
  72. </row>
  73. <row>
  74. <entry>double</entry>
  75. <entry>double</entry>
  76. </row>
  77. <row>
  78. <entry>boolean</entry>
  79. <entry>boolean</entry>
  80. </row>
  81. <row>
  82. <entry>string</entry>
  83. <entry>string</entry>
  84. </row>
  85. <row>
  86. <entry>array</entry>
  87. <entry>array</entry>
  88. </row>
  89. <row>
  90. <entry>associative array</entry>
  91. <entry>struct</entry>
  92. </row>
  93. <row>
  94. <entry>object</entry>
  95. <entry>array</entry>
  96. </row>
  97. </tbody>
  98. </tgroup>
  99. </table>
  100. <note>
  101. <title>Comment est casté un tableau vide ?</title>
  102. <para>Fournir un tableau vide à une méthode XML-RPC est problématique, car il peut être représenté sous
  103. la forme soit d'un tableau, soit d'une structure ("struct"). <classname>Zend_XmlRpc_Client</classname> détecte ce
  104. genre de conditions et fait une requête vers la méthode <code>system.methodSignature</code> du serveur
  105. pour déterminer le type XML-RPC approprié vers le quel casté.</para>
  106. <para>Cependant, ceci peut mener malgré tout à des soucis. Premièrement, les serveurs qui ne supportent
  107. <code>system.methodSignature</code> vont retourner une requête de type échec, et
  108. <classname>Zend_XmlRpc_Client</classname> résultera en un cast de la valeur de type tableau XML-RPC ("array"). De
  109. plus, ceci sous-entend que tout appel avec des arguments de type tableau entraîneront un appel
  110. additionnel au serveur distant.</para>
  111. <para>Pour désactiver entièrement la recherche, vous pouvez appeler la méthode
  112. <code>setSkipSystemLookup()</code> avant de réaliser votre appel XML-RPC :</para>
  113. <programlisting role="php"><![CDATA[
  114. $client->setSkipSystemLookup(true);
  115. $result = $client->call('foo.bar', array(array()));
  116. ]]></programlisting>
  117. </note>
  118. </sect3>
  119. <sect3 id="zend.xmlrpc.value.parameters.xmlrpc-value">
  120. <title>Objets <classname>Zend_XmlRpc_Value</classname> en tant que paramètres</title>
  121. <para>Les paramètres peuvent aussi être des objets <classname>Zend_XmlRpc_Value</classname> qui spécifient alors
  122. exactement un type XML-RPC. Les raisons principales d'utiliser un tel procédé sont : <itemizedlist>
  123. <listitem>
  124. <para>Lorsque vous voulez être certain du type de paramètre (la méthode attend un entier et vous
  125. le récupérez sous forme de chaîne de caractères depuis une base de données).</para>
  126. </listitem>
  127. <listitem>
  128. <para>Lorsque la méthode attend un type <code>base64</code> ou <code>dateTime.iso8601</code>
  129. (ceux-ci n'existant pas nativement dans le langage PHP).</para>
  130. </listitem>
  131. <listitem>
  132. <para>Lorsque la conversion de types (cast) peut échouer (vous voulez passer une valeur XML-RPC
  133. vide comme paramètre. Mais les valeurs vides en PHP sont représentés sous forme de tableaux
  134. vides, or si vous passez un tableau vide à votre méthode <code>call</code>, il va être converti
  135. en un tableau XML-RPC, comme ce n'est pas un tableau associatif).</para>
  136. </listitem>
  137. </itemizedlist></para>
  138. <para>Deux manières existent pour créer des objets <classname>Zend_XmlRpc_Value</classname> : instanciez une
  139. sous-classe <classname>Zend_XmlRpc_Value</classname> directement, ou utilisez une fabrique ("factory method") telle
  140. que <classname>Zend_XmlRpc_Value::getXmlRpcValue()</classname>.</para>
  141. <table id="zend.xmlrpc.value.parameters.xmlrpc-value.table-1">
  142. <title>Objets <classname>Zend_XmlRpc_Value</classname> comme types XML-RPC</title>
  143. <tgroup cols="3">
  144. <thead>
  145. <row>
  146. <entry>XML-RPC Type</entry>
  147. <entry><classname>Zend_XmlRpc_Value</classname> Constante</entry>
  148. <entry><classname>Zend_XmlRpc_Value</classname> Objet</entry>
  149. </row>
  150. </thead>
  151. <tbody>
  152. <row>
  153. <entry>int</entry>
  154. <entry><classname>Zend_XmlRpc_Value::XMLRPC_TYPE_INTEGER</classname></entry>
  155. <entry><classname>Zend_XmlRpc_Value_Integer</classname></entry>
  156. </row>
  157. <row>
  158. <entry>double</entry>
  159. <entry><classname>Zend_XmlRpc_Value::XMLRPC_TYPE_DOUBLE</classname></entry>
  160. <entry><classname>Zend_XmlRpc_Value_Double</classname></entry>
  161. </row>
  162. <row>
  163. <entry>boolean</entry>
  164. <entry><classname>Zend_XmlRpc_Value::XMLRPC_TYPE_BOOLEAN</classname></entry>
  165. <entry><classname>Zend_XmlRpc_Value_Boolean</classname></entry>
  166. </row>
  167. <row>
  168. <entry>string</entry>
  169. <entry><classname>Zend_XmlRpc_Value::XMLRPC_TYPE_STRING</classname></entry>
  170. <entry><classname>Zend_XmlRpc_Value_String</classname></entry>
  171. </row>
  172. <row>
  173. <entry>base64</entry>
  174. <entry><classname>Zend_XmlRpc_Value::XMLRPC_TYPE_BASE64</classname></entry>
  175. <entry><classname>Zend_XmlRpc_Value_Base64</classname></entry>
  176. </row>
  177. <row>
  178. <entry>dateTime.iso8601</entry>
  179. <entry><classname>Zend_XmlRpc_Value::XMLRPC_TYPE_DATETIME</classname></entry>
  180. <entry><classname>Zend_XmlRpc_Value_DateTime</classname></entry>
  181. </row>
  182. <row>
  183. <entry>array</entry>
  184. <entry><classname>Zend_XmlRpc_Value::XMLRPC_TYPE_ARRAY</classname></entry>
  185. <entry><classname>Zend_XmlRpc_Value_Array</classname></entry>
  186. </row>
  187. <row>
  188. <entry>struct</entry>
  189. <entry><classname>Zend_XmlRpc_Value::XMLRPC_TYPE_STRUCT</classname></entry>
  190. <entry><classname>Zend_XmlRpc_Value_Struct</classname></entry>
  191. </row>
  192. </tbody>
  193. </tgroup>
  194. </table>
  195. <para><note>
  196. <title>Conversion automatique</title>
  197. <para>Lorsque vous créez un objet <classname>Zend_XmlRpc_Value</classname>, sa valeur est déterminée par un
  198. type PHP. Celui-ci va être converti vers le type désiré en utilisant le cast PHP. Par exemple si une
  199. chaîne de caractères est donnée comme valeur à un objet <classname>Zend_XmlRpc_Value_Integer</classname>, elle
  200. sera alors convertie suivant la règle <code>(int)$value</code>.</para>
  201. </note></para>
  202. </sect3>
  203. </sect2>
  204. <sect2 id="zend.xmlrpc.client.requests-and-responses">
  205. <title>Objet proxy du serveur</title>
  206. <para>Un autre moyen d'appeler des méthodes avec un client XML-RPC est d'utiliser le proxy du serveur. C'est un
  207. objet PHP qui proxie un espace de nom XML-RPC, en fonctionnant autant que possible comme les objets PHP.</para>
  208. <para>Pour instancier un proxy serveur, appelez <code>getProxy()</code> de <classname>Zend_XmlRpc_Client</classname>. Elle
  209. retourne un objet <classname>Zend_XmlRpc_Client_ServerProxy</classname>. Tout appel de méthode sur l'objet proxy sera
  210. proxié vers le serveur XML-RPC, et les paramètres seront utilisés comme pour une méthode PHP banale.</para>
  211. <example id="zend.xmlrpc.client.requests-and-responses.example-1">
  212. <title>Proxy espace de nom par défaut</title>
  213. <programlisting role="php"><![CDATA[
  214. $client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
  215. $server = $client->getProxy();
  216. // Proxy l'espace de nom par défaut
  217. $hello = $server->test->sayHello(1, 2);
  218. // test.Hello(1, 2) retourne "hello"
  219. ]]></programlisting>
  220. </example>
  221. <para>La méthode <code>getProxy()</code> reçoit un argument optionnel désignant l'espace de nom à utiliser par
  222. le proxy. Par défaut, il s'agit de l'espace général, voici un exemple utilisant un espace de nom
  223. <code>test</code> :</para>
  224. <example id="zend.xmlrpc.client.requests-and-responses.example-2">
  225. <title>Proxy un espace de nom</title>
  226. <programlisting role="php"><![CDATA[
  227. $client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
  228. $test = $client->getProxy('test');
  229. // Proxy l'espace de nommage "test"
  230. $hello = $test->sayHello(1, 2);
  231. // test.Hello(1,2) retourne "hello"
  232. ]]></programlisting>
  233. </example>
  234. <para>Si le serveur distant supporte les espaces de noms imbriqués, alors le proxy les supportera. Par exemple,
  235. si le serveur dans l'exemple ci-dessus acceptait les espaces de noms imbriqués, alors sa méthode
  236. <code>test.foo.bar()</code> aurait pu être appelée via <code>$test-&gt;foo-&gt;bar()</code>.</para>
  237. </sect2>
  238. <sect2 id="zend.xmlrpc.client.error-handling">
  239. <title>Gestion des erreurs</title>
  240. <para>Deux types d'erreurs peuvent être distingués : erreurs HTTP, ou erreurs XML-RPC. L'objet
  241. <classname>Zend_XmlRpc_Client</classname> reconnaît ces erreurs et fournit les moyens de les repérer et de les
  242. gérer.</para>
  243. <sect3 id="zend.xmlrpc.client.error-handling.http">
  244. <title>Erreurs HTTP</title>
  245. <para>Si une erreur HTTP survient, par exemple le serveur renvoie un <code>404 Not Found</code>, alors une
  246. <classname>Zend_XmlRpc_Client_HttpException</classname> sera levée.</para>
  247. <example id="zend.xmlrpc.client.error-handling.http.example-1">
  248. <title>Gérer les erreurs HTTP</title>
  249. <programlisting role="php"><![CDATA[
  250. $client = new Zend_XmlRpc_Client('http://foo/404');
  251. try {
  252. $client->call('bar', array($arg1, $arg2));
  253. } catch (Zend_XmlRpc_Client_HttpException $e) {
  254. // $e->getCode() retourne 404
  255. // $e->getMessage() retourne "Not Found"
  256. }
  257. ]]></programlisting>
  258. </example>
  259. <para>Quelque soit l'utilisation du client XML-RPC, une <classname>Zend_XmlRpc_Client_HttpException</classname> sera
  260. systématiquement levée lorsqu'une erreur HTTP de quelque type que ce soit est rencontrée.</para>
  261. </sect3>
  262. <sect3 id="zend.xmlrpc.client.error-handling.faults">
  263. <title>Erreurs XML-RPC (Faults)</title>
  264. <para>Une erreur XML-RPC peut être assimilée à une exception en PHP. C'est un type spécial retourné par une
  265. des méthodes du client XML-RPC, et ce type contient un message, et un code d'erreur. Les erreurs XML-RPC
  266. seront gérées différemment en fonction du contexte d'utilisation de l'objet
  267. <classname>Zend_XmlRpc_Client</classname>.</para>
  268. <para>Lors de l'utilisation de la méthode <code>call()</code>, ou de l'objet proxy serveur, une erreur
  269. XML-RPC aura pour effet de lancer une <classname>Zend_XmlRpc_Client_FaultException</classname>. Le code et le message
  270. de l'exception seront rendus dans leurs valeurs respectives de la réponse XML-RPC.</para>
  271. <example id="zend.xmlrpc.client.error-handling.faults.example-1">
  272. <title>Gérer les erreurs XML-RPC</title>
  273. <programlisting role="php"><![CDATA[
  274. $client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
  275. try {
  276. $client->call('badMethod');
  277. } catch (Zend_XmlRpc_Client_FaultException $e) {
  278. // $e->getCode() retourne 1
  279. // $e->getMessage() retourne "Unknown method"
  280. }
  281. ]]></programlisting>
  282. </example>
  283. <para>En utilisant <code>call()</code>, une exception <classname>Zend_XmlRpc_Client_FaultException</classname> sera
  284. donc lancée si une erreur survient. Un objet <classname>Zend_XmlRpc_Response</classname> contenant l'erreur sera de
  285. même disponible via la méthode <code>getLastResponse()</code>.</para>
  286. <para>Lors de l'utilisation de la méthode <code>doRequest()</code>, aucune exception ne sera levée si une
  287. erreur XML-RPC survient. Simplement, l'objet <classname>Zend_XmlRpc_Response</classname> retourné contiendra l'erreur.
  288. Vérifiez-en l'état avec <code>isFault()</code>.</para>
  289. </sect3>
  290. </sect2>
  291. <sect2 id="zend.xmlrpc.client.introspection">
  292. <title>Introspection du serveur</title>
  293. <para>Certains serveurs XML-RPC supportent l'introspection de leurs méthodes au travers de l'espace de noms
  294. <code>system.</code> <classname>Zend_XmlRpc_Client</classname> fournit un support d'un tel procédé.</para>
  295. <para>Une instance de <classname>Zend_XmlRpc_Client_ServerIntrospection</classname> sera retournée si vous appelez la
  296. méthode <code>getIntrospector()</code> sur l'objet <classname>Zend_XmlRpcClient</classname>.</para>
  297. </sect2>
  298. <sect2 id="zend.xmlrpc.client.request-to-response">
  299. <title>De la requête à la réponse</title>
  300. <para>Dans les faits, la méthode <code>call()</code> de <classname>Zend_XmlRpc_Client</classname> fabrique un objet
  301. <classname>Zend_XmlRpc_Request</classname> et l'envoie à une méthode <code>doRequest()</code>, qui retourne un objet de
  302. réponse <classname>Zend_XmlRpc_Response</classname>.</para>
  303. <para>La méthode <code>doRequest()</code> est disponible directement si besoin :</para>
  304. <example id="zend.xmlrpc.client.request-to-response.example-1">
  305. <title>Effectuer une requête et récupérer une réponse manuellement</title>
  306. <programlisting role="php"><![CDATA[
  307. $client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
  308. $request = new Zend_XmlRpc_Request();
  309. $request->setMethod('test.sayHello');
  310. $request->setParams(array('foo', 'bar'));
  311. $client->doRequest($request);
  312. // $server->getLastRequest() retoure instanceof Zend_XmlRpc_Request
  313. // $server->getLastResponse() retourne instanceof Zend_XmlRpc_Response
  314. ]]></programlisting>
  315. </example>
  316. <para>Lorsqu'une méthode XML-RPC est appelée, quel qu'en soit le moyen, (<code>call()</code>,
  317. <code>doRequest()</code> ou proxy serveur), le dernier objet de requête, et son homologue de réponse, seront
  318. toujours disponibles, au travers des appels à <code>getLastRequest()</code> et
  319. <code>getLastResponse()</code>.</para>
  320. </sect2>
  321. <sect2 id="zend.xmlrpc.client.http-client">
  322. <title>Client HTTP et tests</title>
  323. <para>Dans tous les exemples utilisés sur cette page, nous ne parlons jamais du client HTTP. Lorsque c'est
  324. nécessaire, une instance de <classname>Zend_Http_Client</classname> sera créée par défaut et injectée dans
  325. <classname>Zend_XmlRpc_Client</classname> de manière automatique.</para>
  326. <para>L'objet client HTTP peut être récupéré à tout moment grâce à la méthode <code>getHttpClient()</code>.
  327. <code>setHttpClient()</code> permet d'injecter un objet <classname>Zend_Http_Client</classname>.</para>
  328. <para><code>setHttpClient()</code> est particulièrement utilisée pour les tests unitaires. Lorsque combinée avec
  329. <classname>Zend_Http_Client_Adapter_Test</classname>, les services Web peuvent être déguisés (émulés) pour les tests.
  330. Voyez les tests unitaires de <classname>Zend_XmlRpc_Client</classname> pour des exemples concrets.</para>
  331. </sect2>
  332. </sect1>