Zend_XmlRpc_Client.xml 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- Reviewed: no -->
  3. <sect1 id="zend.xmlrpc.client">
  4. <title>Zend_XmlRpc_Client</title>
  5. <sect2 id="zend.xmlrpc.client.introduction">
  6. <title>Введение</title>
  7. <para>
  8. Zend Framework поддерживает клиентское использование удаленных
  9. XML-RPC сервисов через пакет <classname>Zend_XmlRpc_Client</classname>.
  10. Его основные возможности включают в себя автоматическое
  11. преобразование типов между PHP и XML-RPC, прокси-объект сервера и
  12. доступ к средствам интроспекции на сервере.
  13. </para>
  14. </sect2>
  15. <sect2 id="zend.xmlrpc.client.method-calls">
  16. <title>Вызов методов</title>
  17. <para>
  18. Конструктор <classname>Zend_XmlRpc_Client</classname> принимает URL удаленного
  19. XML-RPC сервера в качестве первого параметра. Новый экземпляр класса
  20. может использоваться для вызова любых удаленных методов этого
  21. сервера.
  22. </para>
  23. <para>
  24. Для вызова удаленного метода через клиентa XML-RPC инстанцируйте его
  25. и используйте его метод <code>call()</code>. В примере ниже
  26. используется демонстрационный XML-RPC сервер на веб-сайте Zend
  27. Framework. Вы можете использовать его для тестирования или изучения
  28. компонент <classname>Zend_XmlRpc</classname>.
  29. </para>
  30. <example id="zend.xmlrpc.client.method-calls.example-1">
  31. <title>Вызов метода XML-RPC</title>
  32. <programlisting language="php"><![CDATA[
  33. $client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
  34. echo $client->call('test.sayHello');
  35. // hello
  36. ]]></programlisting>
  37. </example>
  38. <para>
  39. Значение XML-RPC, возвращаемое при вызове удаленного метода, будет
  40. автоматически приведено к эквивалентному типу в PHP. В примере выше
  41. возвращается строка (тип <type>String</type> в PHP), и она уже
  42. готова к применению.
  43. </para>
  44. <para>
  45. Первый параметр метода <code>call()</code> принимает имя удаленного
  46. метода, вызов которого требуется. Если удаленный метод требует
  47. каких-либо параметров, то они могут быть переданы методу
  48. <code>call()</code> через второй необязательный параметр в виде
  49. массива значений для последующей передачи удаленному методу:
  50. </para>
  51. <example id="zend.xmlrpc.client.method-calls.example-2">
  52. <title>Вызов метода XML-RPC с параметрами</title>
  53. <programlisting language="php"><![CDATA[
  54. $client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
  55. $arg1 = 1.1;
  56. $arg2 = 'foo';
  57. $result = $client->call('test.sayHello', array($arg1, $arg2));
  58. // возвращаемый результат имеет "родной" для PHP тип
  59. ]]></programlisting>
  60. </example>
  61. <para>
  62. Если удаленный метод не требует параметров, то этот необязательный
  63. параметр можно опустить или передать пустой массив. Массив
  64. параметров для удаленного метода может содержать значения "родного"
  65. для PHP типа, объекты <classname>Zend_XmlRpc_Value</classname>, либо
  66. и то и другое вместе.
  67. </para>
  68. <para>
  69. Метод <code>call()</code> будет автоматически преобразовывать ответ
  70. XML-RPC и возвращать его в эквивалентном "родном" для PHP типе.
  71. Кроме этого, можно получить объект <classname>Zend_XmlRpc_Response</classname>
  72. для возвращенного значения, вызвав метод
  73. <code>getLastResponse()</code> после вызова <code>call()</code>.
  74. </para>
  75. </sect2>
  76. <sect2 id="zend.xmlrpc.value.parameters">
  77. <title>Типы и их преобразование</title>
  78. <para>
  79. Некоторые удаленные методы требуют передачи параметров при вызове.
  80. Они передаются методу <code>call()</code> объекта
  81. <classname>Zend_XmlRpc_Client</classname> в виде массива во втором параметре.
  82. Любой параметр может быть передан в "родном" для PHP типе, который
  83. будет автоматически преобразован в соответствующий тип XML-RPC,
  84. или как объект, представляющий
  85. определенный тип в XML-RPC (один из объектов
  86. <classname>Zend_XmlRpc_Value</classname>).
  87. </para>
  88. <sect3 id="zend.xmlrpc.value.parameters.php-native">
  89. <title>Параметры в "родном" для PHP типе</title>
  90. <para>
  91. Параметры могут передаваться методу <code>call()</code> как
  92. переменные "родного" для PHP типа, это могут быть типы
  93. <type>String</type>, <code>integer</code>, <code>float</code>,
  94. <type>Boolean</type>, <type>Array</type> или
  95. <code>object</code>. В этом случае каждый из этих типов будет
  96. автоматически определен и преобразован в один из типов XML-RPC
  97. согласно следующей таблице:
  98. </para>
  99. <table>
  100. <title>Преобразование типов PHP и XML-RPC</title>
  101. <tgroup cols="2">
  102. <thead>
  103. <row>
  104. <entry>Тип в PHP</entry>
  105. <entry>Тип в XML-RPC</entry>
  106. </row>
  107. </thead>
  108. <tbody>
  109. <row>
  110. <entry>integer</entry>
  111. <entry>int</entry>
  112. </row>
  113. <row>
  114. <entry>double</entry>
  115. <entry>double</entry>
  116. </row>
  117. <row>
  118. <entry>boolean</entry>
  119. <entry>boolean</entry>
  120. </row>
  121. <row>
  122. <entry>string</entry>
  123. <entry>string</entry>
  124. </row>
  125. <row>
  126. <entry>array</entry>
  127. <entry>array</entry>
  128. </row>
  129. <row>
  130. <entry>array (ассоциативный)</entry>
  131. <entry>struct</entry>
  132. </row>
  133. <row>
  134. <entry>object</entry>
  135. <entry>array</entry>
  136. </row>
  137. </tbody>
  138. </tgroup>
  139. </table>
  140. <note>
  141. <title>Какому типу будет соответствовать пустой массив?</title>
  142. <para>
  143. Передача пустого массива методу XML-RPC несет в себе
  144. потенциальную проблему, т.к. он может быть представлен
  145. и массивом, и структурой. <classname>Zend_XmlRpc_Client</classname>
  146. в этом случае делает запрос к методу сервера
  147. <code>system.methodSignature</code> для определения
  148. требуемого типа аргумента и производит соответствующее
  149. преобразование.
  150. </para>
  151. <para>
  152. Но такое решение само по себе тоже может быть источником
  153. проблем. Во-первых, сервера, которые не поддерживают метод
  154. <code>system.methodSignature</code>, будут журналировать это
  155. как ошибочные вызовы, в этом случае
  156. <classname>Zend_XmlRpc_Client</classname> будет производить
  157. преобразование значения к типу array в XML-RPC.
  158. Кроме того, это приводит к дополнительным вызовам к
  159. удаленному серверу в случае передачи аргументов в виде
  160. массивов.
  161. </para>
  162. <para>
  163. Для того, чтобы полностью отключить эти вызовы, вы можете
  164. вызвать метод <code>setSkipSystemLookup()</code> до
  165. собственно запроса к методу XML-RPC:
  166. </para>
  167. <programlisting language="php"><![CDATA[
  168. $client->setSkipSystemLookup(true);
  169. $result = $client->call('foo.bar', array(array()));
  170. ]]></programlisting>
  171. </note>
  172. </sect3>
  173. <sect3 id="zend.xmlrpc.value.parameters.xmlrpc-value">
  174. <title>Параметры в виде объектов Zend_XmlRpc_Value</title>
  175. <para>
  176. Параметры могут также создаваться как экземпляры
  177. <classname>Zend_XmlRpc_Value</classname> для точного указания типа
  178. XML-RPC. Основные причины для этого:
  179. <itemizedlist>
  180. <listitem>
  181. <para>
  182. Вы хотите быть уверенными в том, что
  183. процедуре передается корректный тип параметра
  184. (т.е. процедура требует целочисленное значение, а
  185. вы можете получать его из БД в виде
  186. строки)
  187. </para>
  188. </listitem>
  189. <listitem>
  190. <para>
  191. Удаленная процедура требует тип <code>base64</code>
  192. или <code>dateTime.iso8601</code> (которых нет среди
  193. "родных" для PHP типов).
  194. </para>
  195. </listitem>
  196. <listitem>
  197. <para>
  198. Автоматическое преобразование может работать
  199. неправильно (например, вы хотите передать пустую
  200. структуру XML-RPC в качестве параметра. Пустая структура
  201. представляется в PHP пустым массивом, но если вы
  202. передаете пустой массив в качестве параметра, то он
  203. преобразовывается в массив XML-RPC, т.к. не
  204. является ассоциативным массивом)
  205. </para>
  206. </listitem>
  207. </itemizedlist>
  208. </para>
  209. <para>
  210. Есть два способа создания объектов <classname>Zend_XmlRpc_Value</classname> ―
  211. непосредственное инстанцирование одного из подклассов
  212. <classname>Zend_XmlRpc_Value</classname> и использование статического
  213. фабричного метода
  214. <classname>Zend_XmlRpc_Value::getXmlRpcValue()</classname>.
  215. </para>
  216. <table id="zend.xmlrpc.value.parameters.xmlrpc-value.table-1">
  217. <title>Объекты Zend_XmlRpc_Value для типов XML-RPC</title>
  218. <tgroup cols="3">
  219. <thead>
  220. <row>
  221. <entry>Тип XML-RPC</entry>
  222. <entry>Константа <classname>Zend_XmlRpc_Value</classname></entry>
  223. <entry>Объект <classname>Zend_XmlRpc_Value</classname></entry>
  224. </row>
  225. </thead>
  226. <tbody>
  227. <row>
  228. <entry>int</entry>
  229. <entry><code>Zend_XmlRpc_Value::XMLRPC_TYPE_INTEGER</code></entry>
  230. <entry><classname>Zend_XmlRpc_Value_Integer</classname></entry>
  231. </row>
  232. <row>
  233. <entry>double</entry>
  234. <entry><code>Zend_XmlRpc_Value::XMLRPC_TYPE_DOUBLE</code></entry>
  235. <entry><classname>Zend_XmlRpc_Value_Double</classname></entry>
  236. </row>
  237. <row>
  238. <entry>boolean</entry>
  239. <entry><code>Zend_XmlRpc_Value::XMLRPC_TYPE_BOOLEAN</code></entry>
  240. <entry><classname>Zend_XmlRpc_Value_Boolean</classname></entry>
  241. </row>
  242. <row>
  243. <entry>string</entry>
  244. <entry><code>Zend_XmlRpc_Value::XMLRPC_TYPE_STRING</code></entry>
  245. <entry><classname>Zend_XmlRpc_Value_String</classname></entry>
  246. </row>
  247. <row>
  248. <entry>base64</entry>
  249. <entry><code>Zend_XmlRpc_Value::XMLRPC_TYPE_BASE64</code></entry>
  250. <entry><classname>Zend_XmlRpc_Value_Base64</classname></entry>
  251. </row>
  252. <row>
  253. <entry>dateTime.iso8601</entry>
  254. <entry><code>Zend_XmlRpc_Value::XMLRPC_TYPE_DATETIME</code></entry>
  255. <entry><classname>Zend_XmlRpc_Value_DateTime</classname></entry>
  256. </row>
  257. <row>
  258. <entry>array</entry>
  259. <entry><code>Zend_XmlRpc_Value::XMLRPC_TYPE_ARRAY</code></entry>
  260. <entry><classname>Zend_XmlRpc_Value_Array</classname></entry>
  261. </row>
  262. <row>
  263. <entry>struct</entry>
  264. <entry><code>Zend_XmlRpc_Value::XMLRPC_TYPE_STRUCT</code></entry>
  265. <entry><classname>Zend_XmlRpc_Value_Struct</classname></entry>
  266. </row>
  267. </tbody>
  268. </tgroup>
  269. </table>
  270. <para>
  271. <note>
  272. <title>Автоматическое преобразование</title>
  273. <para>
  274. Когда создается новый объект
  275. <classname>Zend_XmlRpc_Value</classname>, его значение
  276. устанавливается в "родном" для PHP типе. Тип в PHP будет
  277. преобразован к определенному типу средствами PHP.
  278. Например, если в качестве значения для объекта
  279. <classname>Zend_XmlRpc_Value_Integer</classname> была передана
  280. строка, то она будет преобразована через
  281. <code>(int)$value</code>.
  282. </para>
  283. </note>
  284. </para>
  285. </sect3>
  286. </sect2>
  287. <sect2 id="zend.xmlrpc.client.requests-and-responses">
  288. <title>Прокси-объект сервера</title>
  289. <para>
  290. Другим способом вызова удаленных методов через клиента XML-RPC
  291. является использование "заместителя" сервера. Это PHP-объект,
  292. который предоставляет интерфейс к удаленному пространству имен
  293. XML-RPC, делая работу с ним максимально близкой к работе с обычным
  294. объектом в PHP.
  295. </para>
  296. <para>
  297. Для того, чтобы инстанцировать "заместителя" сервера, вызовите
  298. метод <code>getProxy()</code> объекта
  299. <classname>Zend_XmlRpc_Client</classname>. Он вернет объект класса
  300. <classname>Zend_XmlRpc_Client_ServerProxy</classname>.
  301. Любые вызовы методов прокси-объекта
  302. сервера будет перенаправлены к удаленному серверу, параметры могут
  303. передаваться так же, как и для любых других методов в PHP.
  304. </para>
  305. <example id="zend.xmlrpc.client.requests-and-responses.example-1">
  306. <title>Прокси-объект к пространству имен по умолчанию</title>
  307. <programlisting language="php"><![CDATA[
  308. $client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
  309. // Создание прокси-объекта к пространству имен по умолчанию
  310. $server = $client->getProxy();
  311. $hello = $server->test->sayHello(1, 2);
  312. // test.Hello(1, 2) возвращает "hello"
  313. ]]></programlisting>
  314. </example>
  315. <para>
  316. Метод <code>getProxy()</code> принимает необязательный аргумент,
  317. указывающий, к какому пространству имен следует создать
  318. прокси-объект. Если этот аргумент не был указан, то то будет
  319. использоваться пространство имен по умолчанию. В следующем примере
  320. используется пространство имен <code>test</code>:
  321. </para>
  322. <example id="zend.xmlrpc.client.requests-and-responses.example-2">
  323. <title>Прокси-объект к произвольному пространству имен</title>
  324. <programlisting language="php"><![CDATA[
  325. $client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
  326. // Создание прокси-объекта к пространству имен "test"
  327. $test = $client->getProxy('test');
  328. $hello = $test->sayHello(1, 2);
  329. // test.Hello(1,2) возвращает "hello"
  330. ]]></programlisting>
  331. </example>
  332. <para>
  333. Если удаленный сервер поддерживает сколько угодно вложенные
  334. пространства имен, то они также могут использоваться через
  335. прокси-объект сервера. Например, если сервер в примере выше имеет
  336. метод <code>test.foo.bar()</code>, то он может вызываться следующим
  337. образом: <varname>$test->foo->bar()</varname>.
  338. </para>
  339. </sect2>
  340. <sect2 id="zend.xmlrpc.client.error-handling">
  341. <title>Обработка ошибок</title>
  342. <para>
  343. При вызове методов XML-RPC могут могут быть ошибки двух типов: HTTP и
  344. XML-RPC. <classname>Zend_XmlRpc_Client</classname> распознает оба типа,
  345. позволяя обнаруживать и отлавливать их независимо друг от друга.
  346. </para>
  347. <sect3 id="zend.xmlrpc.client.error-handling.http">
  348. <title>Ошибки HTTP</title>
  349. <para>
  350. Если произошла ошибка HTTP - например, удаленный HTTP-сервер
  351. вернул код <code>404 Not Found</code>, - то будет сгенерировано
  352. исключение <classname>Zend_XmlRpc_Client_HttpException</classname>.
  353. </para>
  354. <example id="zend.xmlrpc.client.error-handling.http.example-1">
  355. <title>Обработка ошибок HTTP</title>
  356. <programlisting language="php"><![CDATA[
  357. $client = new Zend_XmlRpc_Client('http://foo/404');
  358. try {
  359. $client->call('bar', array($arg1, $arg2));
  360. } catch (Zend_XmlRpc_HttpException $e) {
  361. // $e->getCode() возвращает 404
  362. // $e->getMessage() возвращает "Not Found"
  363. }
  364. ]]></programlisting>
  365. </example>
  366. <para>
  367. Независимо от того, какой клиент XML-RPC используется, всякий
  368. раз, когда происходит ошибка HTTP, генерируется исключение
  369. <classname>Zend_XmlRpc_Client_HttpException</classname>.
  370. </para>
  371. </sect3>
  372. <sect3 id="zend.xmlrpc.client.error-handling.faults">
  373. <title>Ошибки XML-RPC</title>
  374. <para>
  375. Ошибка XML-RPC аналогична исключению в PHP. Это специальный тип,
  376. возвращаемый при вызове метода XML-RPC и включающий в себя код и
  377. сообщение ошибки. Ошибки XML-RPC обрабатываются по-разному,
  378. в зависимости от контекста использования
  379. <classname>Zend_XmlRpc_Client</classname>.
  380. </para>
  381. <para>
  382. Если используется метод <code>call()</code> или прокси-объект
  383. сервера, то ошибка XML-RPC приведет к тому, что будет
  384. сгенерировано исключение
  385. <classname>Zend_XmlRpc_Client_FaultException</classname>. Код и сообщение
  386. исключения будут в точности соответствовать значениям в
  387. возвращенном ответе с сообщением об ошибке.
  388. </para>
  389. <example id="zend.xmlrpc.client.error-handling.faults.example-1">
  390. <title>Обработка ошибок XML-RPC</title>
  391. <programlisting language="php"><![CDATA[
  392. $client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
  393. try {
  394. $client->call('badMethod');
  395. } catch (Zend_XmlRpc_FaultException $e) {
  396. // $e->getCode() возвращает 1
  397. // $e->getMessage() возвращает "Unknown method"
  398. }
  399. ]]></programlisting>
  400. </example>
  401. <para>
  402. Если для выполнения запроса используется метод
  403. <code>call()</code>, то в случае ошибки будет сгенерировано
  404. исключение <classname>Zend_XmlRpc_FaultException</classname>. Объект
  405. <classname>Zend_XmlRpc_Response</classname>, содержащий возвращенную
  406. ошибку, можно также получить через метод
  407. <code>getLastResponse()</code>.
  408. </para>
  409. <para>
  410. Если для выполнения запроса используется метод
  411. <code>doRequest()</code>, то исключение не генерируется. Вместо
  412. этого будет возвращен объект <classname>Zend_XmlRpc_Response</classname>,
  413. содержащий возвращенную XML-RPC ошибку. Проверить, содержит ли
  414. объект ошибку, можно через метод <code>isFault()</code> объекта
  415. <classname>Zend_XmlRpc_Response</classname>.
  416. </para>
  417. </sect3>
  418. </sect2>
  419. <sect2 id="zend.xmlrpc.client.introspection">
  420. <title>Интроспекция сервера</title>
  421. <para>
  422. Некоторые XML-RPC сервера поддерживают интроспекцию методов
  423. под пространством имен <code>system.</code>.
  424. <classname>Zend_XmlRpc_Client</classname> предоставляет специальную поддержку
  425. для серверов с этой возможностью.
  426. </para>
  427. <para>
  428. Экземпляр <classname>Zend_XmlRpc_Client_ServerIntrospection</classname> может
  429. быть получен через вызов метода <code>getIntrospector()</code>
  430. класса <classname>Zend_XmlRpcClient</classname>. Далее он может использоваться
  431. для выполнения операций интроспекции на сервере.
  432. </para>
  433. </sect2>
  434. <sect2 id="zend.xmlrpc.client.request-to-response">
  435. <title>От запроса к ответу</title>
  436. <para>
  437. Метод <code>call()</code> экземпляра <classname>Zend_XmlRpc_Client</classname>
  438. в процессе выполнения строит объект запроса
  439. (<classname>Zend_XmlRpc_Request</classname>) и передает его другому методу
  440. <code>doRequest()</code>, который возвращает объект ответа
  441. (<classname>Zend_XmlRpc_Response</classname>).
  442. </para>
  443. <para>
  444. Метод <code>doRequest()</code> также доступен для непосредственного
  445. использования:
  446. </para>
  447. <example id="zend.xmlrpc.client.request-to-response.example-1">
  448. <title>Выполнение запроса</title>
  449. <programlisting language="php"><![CDATA[
  450. $client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
  451. $request = new Zend_XmlRpc_Request();
  452. $request->setMethod('test.sayHello');
  453. $request->setParams(array('foo', 'bar'));
  454. $client->doRequest($request);
  455. // $server->getLastRequest() возвращает экземпляр Zend_XmlRpc_Request
  456. // $server->getLastResponse() возвращает экземпляр Zend_XmlRpc_Response
  457. ]]></programlisting>
  458. </example>
  459. <para>
  460. После того, как через клиента был вызван метод XML-RPC (через
  461. методы <code>call()</code>, <code>doRequest()</code> или через
  462. прокси-объект сервера), всегда можно получить объекты последнего запроса и
  463. ответа на него через методы <code>getLastRequest()</code> и
  464. <code>getLastResponse()</code> соответственно.
  465. </para>
  466. </sect2>
  467. <sect2 id="zend.xmlrpc.client.http-client">
  468. <title>HTTP-клиент и тестирование</title>
  469. <para>
  470. Ни в одном из предыдущих примеров не указывался HTTP-клиент. В
  471. этом случае создается новый экземпляр <classname>Zend_Http_Client</classname>
  472. с настройками по умолчанию и автоматически используется
  473. клиентом <classname>Zend_XmlRpc_Client</classname>.
  474. </para>
  475. <para>
  476. HTTP-клиент может быть получен в любое время через метод
  477. <code>getHttpClient()</code>. В большинстве случаев достаточно
  478. использование HTTP-клиента по умолчанию. Тем не менее, метод
  479. <code>setHttpClient()</code> позволяет установить HTTP-клиент,
  480. отличный от принятого по умолчанию.
  481. </para>
  482. <para>
  483. <code>setHttpClient()</code> может быть полезен при
  484. unit-тестировании. При совместном использовании с
  485. <classname>Zend_Http_Client_Adapter_Test</classname> можно имитировать
  486. удаленные сервисы для тестирования. В качестве примера реализации
  487. рассмотрите unit-тесты для <classname>Zend_XmlRpc_Client</classname>,
  488. входящие в поставку Zend Framework.
  489. </para>
  490. </sect2>
  491. </sect1>
  492. <!--
  493. vim:se ts=4 sw=4 et:
  494. -->