| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- Reviewed: no -->
- <sect1 id="zend.xmlrpc.client">
- <title>Zend_XmlRpc_Client</title>
- <sect2 id="zend.xmlrpc.client.introduction">
- <title>Введение</title>
- <para>
- Zend Framework поддерживает клиентское использование удаленных
- XML-RPC сервисов через пакет <classname>Zend_XmlRpc_Client</classname>.
- Его основные возможности включают в себя автоматическое
- преобразование типов между PHP и XML-RPC, прокси-объект сервера и
- доступ к средствам интроспекции на сервере.
- </para>
- </sect2>
- <sect2 id="zend.xmlrpc.client.method-calls">
- <title>Вызов методов</title>
- <para>
- Конструктор <classname>Zend_XmlRpc_Client</classname> принимает URL удаленного
- XML-RPC сервера в качестве первого параметра. Новый экземпляр класса
- может использоваться для вызова любых удаленных методов этого
- сервера.
- </para>
- <para>
- Для вызова удаленного метода через клиентa XML-RPC инстанцируйте его
- и используйте его метод <code>call()</code>. В примере ниже
- используется демонстрационный XML-RPC сервер на веб-сайте Zend
- Framework. Вы можете использовать его для тестирования или изучения
- компонент <classname>Zend_XmlRpc</classname>.
- </para>
- <example id="zend.xmlrpc.client.method-calls.example-1">
- <title>Вызов метода XML-RPC</title>
- <programlisting language="php"><![CDATA[
- $client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
- echo $client->call('test.sayHello');
- // hello
- ]]></programlisting>
- </example>
- <para>
- Значение XML-RPC, возвращаемое при вызове удаленного метода, будет
- автоматически приведено к эквивалентному типу в PHP. В примере выше
- возвращается строка (тип <type>String</type> в PHP), и она уже
- готова к применению.
- </para>
- <para>
- Первый параметр метода <code>call()</code> принимает имя удаленного
- метода, вызов которого требуется. Если удаленный метод требует
- каких-либо параметров, то они могут быть переданы методу
- <code>call()</code> через второй необязательный параметр в виде
- массива значений для последующей передачи удаленному методу:
- </para>
- <example id="zend.xmlrpc.client.method-calls.example-2">
- <title>Вызов метода XML-RPC с параметрами</title>
- <programlisting language="php"><![CDATA[
- $client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
- $arg1 = 1.1;
- $arg2 = 'foo';
- $result = $client->call('test.sayHello', array($arg1, $arg2));
- // возвращаемый результат имеет "родной" для PHP тип
- ]]></programlisting>
- </example>
- <para>
- Если удаленный метод не требует параметров, то этот необязательный
- параметр можно опустить или передать пустой массив. Массив
- параметров для удаленного метода может содержать значения "родного"
- для PHP типа, объекты <classname>Zend_XmlRpc_Value</classname>, либо
- и то и другое вместе.
- </para>
- <para>
- Метод <code>call()</code> будет автоматически преобразовывать ответ
- XML-RPC и возвращать его в эквивалентном "родном" для PHP типе.
- Кроме этого, можно получить объект <classname>Zend_XmlRpc_Response</classname>
- для возвращенного значения, вызвав метод
- <code>getLastResponse()</code> после вызова <code>call()</code>.
- </para>
- </sect2>
- <sect2 id="zend.xmlrpc.value.parameters">
- <title>Типы и их преобразование</title>
- <para>
- Некоторые удаленные методы требуют передачи параметров при вызове.
- Они передаются методу <code>call()</code> объекта
- <classname>Zend_XmlRpc_Client</classname> в виде массива во втором параметре.
- Любой параметр может быть передан в "родном" для PHP типе, который
- будет автоматически преобразован в соответствующий тип XML-RPC,
- или как объект, представляющий
- определенный тип в XML-RPC (один из объектов
- <classname>Zend_XmlRpc_Value</classname>).
- </para>
- <sect3 id="zend.xmlrpc.value.parameters.php-native">
- <title>Параметры в "родном" для PHP типе</title>
- <para>
- Параметры могут передаваться методу <code>call()</code> как
- переменные "родного" для PHP типа, это могут быть типы
- <type>String</type>, <code>integer</code>, <code>float</code>,
- <type>Boolean</type>, <type>Array</type> или
- <code>object</code>. В этом случае каждый из этих типов будет
- автоматически определен и преобразован в один из типов XML-RPC
- согласно следующей таблице:
- </para>
- <table>
- <title>Преобразование типов PHP и XML-RPC</title>
- <tgroup cols="2">
- <thead>
- <row>
- <entry>Тип в PHP</entry>
- <entry>Тип в XML-RPC</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>integer</entry>
- <entry>int</entry>
- </row>
- <row>
- <entry>double</entry>
- <entry>double</entry>
- </row>
- <row>
- <entry>boolean</entry>
- <entry>boolean</entry>
- </row>
- <row>
- <entry>string</entry>
- <entry>string</entry>
- </row>
- <row>
- <entry>array</entry>
- <entry>array</entry>
- </row>
- <row>
- <entry>array (ассоциативный)</entry>
- <entry>struct</entry>
- </row>
- <row>
- <entry>object</entry>
- <entry>array</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <note>
- <title>Какому типу будет соответствовать пустой массив?</title>
- <para>
- Передача пустого массива методу XML-RPC несет в себе
- потенциальную проблему, т.к. он может быть представлен
- и массивом, и структурой. <classname>Zend_XmlRpc_Client</classname>
- в этом случае делает запрос к методу сервера
- <code>system.methodSignature</code> для определения
- требуемого типа аргумента и производит соответствующее
- преобразование.
- </para>
- <para>
- Но такое решение само по себе тоже может быть источником
- проблем. Во-первых, сервера, которые не поддерживают метод
- <code>system.methodSignature</code>, будут журналировать это
- как ошибочные вызовы, в этом случае
- <classname>Zend_XmlRpc_Client</classname> будет производить
- преобразование значения к типу array в XML-RPC.
- Кроме того, это приводит к дополнительным вызовам к
- удаленному серверу в случае передачи аргументов в виде
- массивов.
- </para>
- <para>
- Для того, чтобы полностью отключить эти вызовы, вы можете
- вызвать метод <code>setSkipSystemLookup()</code> до
- собственно запроса к методу XML-RPC:
- </para>
- <programlisting language="php"><![CDATA[
- $client->setSkipSystemLookup(true);
- $result = $client->call('foo.bar', array(array()));
- ]]></programlisting>
- </note>
- </sect3>
- <sect3 id="zend.xmlrpc.value.parameters.xmlrpc-value">
- <title>Параметры в виде объектов Zend_XmlRpc_Value</title>
- <para>
- Параметры могут также создаваться как экземпляры
- <classname>Zend_XmlRpc_Value</classname> для точного указания типа
- XML-RPC. Основные причины для этого:
- <itemizedlist>
- <listitem>
- <para>
- Вы хотите быть уверенными в том, что
- процедуре передается корректный тип параметра
- (т.е. процедура требует целочисленное значение, а
- вы можете получать его из БД в виде
- строки)
- </para>
- </listitem>
- <listitem>
- <para>
- Удаленная процедура требует тип <code>base64</code>
- или <code>dateTime.iso8601</code> (которых нет среди
- "родных" для PHP типов).
- </para>
- </listitem>
- <listitem>
- <para>
- Автоматическое преобразование может работать
- неправильно (например, вы хотите передать пустую
- структуру XML-RPC в качестве параметра. Пустая структура
- представляется в PHP пустым массивом, но если вы
- передаете пустой массив в качестве параметра, то он
- преобразовывается в массив XML-RPC, т.к. не
- является ассоциативным массивом)
- </para>
- </listitem>
- </itemizedlist>
- </para>
- <para>
- Есть два способа создания объектов <classname>Zend_XmlRpc_Value</classname> ―
- непосредственное инстанцирование одного из подклассов
- <classname>Zend_XmlRpc_Value</classname> и использование статического
- фабричного метода
- <classname>Zend_XmlRpc_Value::getXmlRpcValue()</classname>.
- </para>
- <table id="zend.xmlrpc.value.parameters.xmlrpc-value.table-1">
- <title>Объекты Zend_XmlRpc_Value для типов XML-RPC</title>
- <tgroup cols="3">
- <thead>
- <row>
- <entry>Тип XML-RPC</entry>
- <entry>Константа <classname>Zend_XmlRpc_Value</classname></entry>
- <entry>Объект <classname>Zend_XmlRpc_Value</classname></entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>int</entry>
- <entry><code>Zend_XmlRpc_Value::XMLRPC_TYPE_INTEGER</code></entry>
- <entry><classname>Zend_XmlRpc_Value_Integer</classname></entry>
- </row>
- <row>
- <entry>double</entry>
- <entry><code>Zend_XmlRpc_Value::XMLRPC_TYPE_DOUBLE</code></entry>
- <entry><classname>Zend_XmlRpc_Value_Double</classname></entry>
- </row>
- <row>
- <entry>boolean</entry>
- <entry><code>Zend_XmlRpc_Value::XMLRPC_TYPE_BOOLEAN</code></entry>
- <entry><classname>Zend_XmlRpc_Value_Boolean</classname></entry>
- </row>
- <row>
- <entry>string</entry>
- <entry><code>Zend_XmlRpc_Value::XMLRPC_TYPE_STRING</code></entry>
- <entry><classname>Zend_XmlRpc_Value_String</classname></entry>
- </row>
- <row>
- <entry>base64</entry>
- <entry><code>Zend_XmlRpc_Value::XMLRPC_TYPE_BASE64</code></entry>
- <entry><classname>Zend_XmlRpc_Value_Base64</classname></entry>
- </row>
- <row>
- <entry>dateTime.iso8601</entry>
- <entry><code>Zend_XmlRpc_Value::XMLRPC_TYPE_DATETIME</code></entry>
- <entry><classname>Zend_XmlRpc_Value_DateTime</classname></entry>
- </row>
- <row>
- <entry>array</entry>
- <entry><code>Zend_XmlRpc_Value::XMLRPC_TYPE_ARRAY</code></entry>
- <entry><classname>Zend_XmlRpc_Value_Array</classname></entry>
- </row>
- <row>
- <entry>struct</entry>
- <entry><code>Zend_XmlRpc_Value::XMLRPC_TYPE_STRUCT</code></entry>
- <entry><classname>Zend_XmlRpc_Value_Struct</classname></entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>
- <note>
- <title>Автоматическое преобразование</title>
- <para>
- Когда создается новый объект
- <classname>Zend_XmlRpc_Value</classname>, его значение
- устанавливается в "родном" для PHP типе. Тип в PHP будет
- преобразован к определенному типу средствами PHP.
- Например, если в качестве значения для объекта
- <classname>Zend_XmlRpc_Value_Integer</classname> была передана
- строка, то она будет преобразована через
- <code>(int)$value</code>.
- </para>
- </note>
- </para>
- </sect3>
- </sect2>
- <sect2 id="zend.xmlrpc.client.requests-and-responses">
- <title>Прокси-объект сервера</title>
- <para>
- Другим способом вызова удаленных методов через клиента XML-RPC
- является использование "заместителя" сервера. Это PHP-объект,
- который предоставляет интерфейс к удаленному пространству имен
- XML-RPC, делая работу с ним максимально близкой к работе с обычным
- объектом в PHP.
- </para>
- <para>
- Для того, чтобы инстанцировать "заместителя" сервера, вызовите
- метод <code>getProxy()</code> объекта
- <classname>Zend_XmlRpc_Client</classname>. Он вернет объект класса
- <classname>Zend_XmlRpc_Client_ServerProxy</classname>.
- Любые вызовы методов прокси-объекта
- сервера будет перенаправлены к удаленному серверу, параметры могут
- передаваться так же, как и для любых других методов в PHP.
- </para>
- <example id="zend.xmlrpc.client.requests-and-responses.example-1">
- <title>Прокси-объект к пространству имен по умолчанию</title>
- <programlisting language="php"><![CDATA[
- $client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
- // Создание прокси-объекта к пространству имен по умолчанию
- $server = $client->getProxy();
- $hello = $server->test->sayHello(1, 2);
- // test.Hello(1, 2) возвращает "hello"
- ]]></programlisting>
- </example>
- <para>
- Метод <code>getProxy()</code> принимает необязательный аргумент,
- указывающий, к какому пространству имен следует создать
- прокси-объект. Если этот аргумент не был указан, то то будет
- использоваться пространство имен по умолчанию. В следующем примере
- используется пространство имен <code>test</code>:
- </para>
- <example id="zend.xmlrpc.client.requests-and-responses.example-2">
- <title>Прокси-объект к произвольному пространству имен</title>
- <programlisting language="php"><![CDATA[
- $client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
- // Создание прокси-объекта к пространству имен "test"
- $test = $client->getProxy('test');
- $hello = $test->sayHello(1, 2);
- // test.Hello(1,2) возвращает "hello"
- ]]></programlisting>
- </example>
- <para>
- Если удаленный сервер поддерживает сколько угодно вложенные
- пространства имен, то они также могут использоваться через
- прокси-объект сервера. Например, если сервер в примере выше имеет
- метод <code>test.foo.bar()</code>, то он может вызываться следующим
- образом: <varname>$test->foo->bar()</varname>.
- </para>
- </sect2>
- <sect2 id="zend.xmlrpc.client.error-handling">
- <title>Обработка ошибок</title>
- <para>
- При вызове методов XML-RPC могут могут быть ошибки двух типов: HTTP и
- XML-RPC. <classname>Zend_XmlRpc_Client</classname> распознает оба типа,
- позволяя обнаруживать и отлавливать их независимо друг от друга.
- </para>
- <sect3 id="zend.xmlrpc.client.error-handling.http">
- <title>Ошибки HTTP</title>
- <para>
- Если произошла ошибка HTTP - например, удаленный HTTP-сервер
- вернул код <code>404 Not Found</code>, - то будет сгенерировано
- исключение <classname>Zend_XmlRpc_Client_HttpException</classname>.
- </para>
- <example id="zend.xmlrpc.client.error-handling.http.example-1">
- <title>Обработка ошибок HTTP</title>
- <programlisting language="php"><![CDATA[
- $client = new Zend_XmlRpc_Client('http://foo/404');
- try {
- $client->call('bar', array($arg1, $arg2));
- } catch (Zend_XmlRpc_HttpException $e) {
- // $e->getCode() возвращает 404
- // $e->getMessage() возвращает "Not Found"
- }
- ]]></programlisting>
- </example>
- <para>
- Независимо от того, какой клиент XML-RPC используется, всякий
- раз, когда происходит ошибка HTTP, генерируется исключение
- <classname>Zend_XmlRpc_Client_HttpException</classname>.
- </para>
- </sect3>
- <sect3 id="zend.xmlrpc.client.error-handling.faults">
- <title>Ошибки XML-RPC</title>
- <para>
- Ошибка XML-RPC аналогична исключению в PHP. Это специальный тип,
- возвращаемый при вызове метода XML-RPC и включающий в себя код и
- сообщение ошибки. Ошибки XML-RPC обрабатываются по-разному,
- в зависимости от контекста использования
- <classname>Zend_XmlRpc_Client</classname>.
- </para>
- <para>
- Если используется метод <code>call()</code> или прокси-объект
- сервера, то ошибка XML-RPC приведет к тому, что будет
- сгенерировано исключение
- <classname>Zend_XmlRpc_Client_FaultException</classname>. Код и сообщение
- исключения будут в точности соответствовать значениям в
- возвращенном ответе с сообщением об ошибке.
- </para>
- <example id="zend.xmlrpc.client.error-handling.faults.example-1">
- <title>Обработка ошибок XML-RPC</title>
- <programlisting language="php"><![CDATA[
- $client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
- try {
- $client->call('badMethod');
- } catch (Zend_XmlRpc_FaultException $e) {
- // $e->getCode() возвращает 1
- // $e->getMessage() возвращает "Unknown method"
- }
- ]]></programlisting>
- </example>
- <para>
- Если для выполнения запроса используется метод
- <code>call()</code>, то в случае ошибки будет сгенерировано
- исключение <classname>Zend_XmlRpc_FaultException</classname>. Объект
- <classname>Zend_XmlRpc_Response</classname>, содержащий возвращенную
- ошибку, можно также получить через метод
- <code>getLastResponse()</code>.
- </para>
- <para>
- Если для выполнения запроса используется метод
- <code>doRequest()</code>, то исключение не генерируется. Вместо
- этого будет возвращен объект <classname>Zend_XmlRpc_Response</classname>,
- содержащий возвращенную XML-RPC ошибку. Проверить, содержит ли
- объект ошибку, можно через метод <code>isFault()</code> объекта
- <classname>Zend_XmlRpc_Response</classname>.
- </para>
- </sect3>
- </sect2>
- <sect2 id="zend.xmlrpc.client.introspection">
- <title>Интроспекция сервера</title>
- <para>
- Некоторые XML-RPC сервера поддерживают интроспекцию методов
- под пространством имен <code>system.</code>.
- <classname>Zend_XmlRpc_Client</classname> предоставляет специальную поддержку
- для серверов с этой возможностью.
- </para>
- <para>
- Экземпляр <classname>Zend_XmlRpc_Client_ServerIntrospection</classname> может
- быть получен через вызов метода <code>getIntrospector()</code>
- класса <classname>Zend_XmlRpcClient</classname>. Далее он может использоваться
- для выполнения операций интроспекции на сервере.
- </para>
- </sect2>
- <sect2 id="zend.xmlrpc.client.request-to-response">
- <title>От запроса к ответу</title>
- <para>
- Метод <code>call()</code> экземпляра <classname>Zend_XmlRpc_Client</classname>
- в процессе выполнения строит объект запроса
- (<classname>Zend_XmlRpc_Request</classname>) и передает его другому методу
- <code>doRequest()</code>, который возвращает объект ответа
- (<classname>Zend_XmlRpc_Response</classname>).
- </para>
- <para>
- Метод <code>doRequest()</code> также доступен для непосредственного
- использования:
- </para>
- <example id="zend.xmlrpc.client.request-to-response.example-1">
- <title>Выполнение запроса</title>
- <programlisting language="php"><![CDATA[
- $client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
- $request = new Zend_XmlRpc_Request();
- $request->setMethod('test.sayHello');
- $request->setParams(array('foo', 'bar'));
- $client->doRequest($request);
- // $server->getLastRequest() возвращает экземпляр Zend_XmlRpc_Request
- // $server->getLastResponse() возвращает экземпляр Zend_XmlRpc_Response
- ]]></programlisting>
- </example>
- <para>
- После того, как через клиента был вызван метод XML-RPC (через
- методы <code>call()</code>, <code>doRequest()</code> или через
- прокси-объект сервера), всегда можно получить объекты последнего запроса и
- ответа на него через методы <code>getLastRequest()</code> и
- <code>getLastResponse()</code> соответственно.
- </para>
- </sect2>
- <sect2 id="zend.xmlrpc.client.http-client">
- <title>HTTP-клиент и тестирование</title>
- <para>
- Ни в одном из предыдущих примеров не указывался HTTP-клиент. В
- этом случае создается новый экземпляр <classname>Zend_Http_Client</classname>
- с настройками по умолчанию и автоматически используется
- клиентом <classname>Zend_XmlRpc_Client</classname>.
- </para>
- <para>
- HTTP-клиент может быть получен в любое время через метод
- <code>getHttpClient()</code>. В большинстве случаев достаточно
- использование HTTP-клиента по умолчанию. Тем не менее, метод
- <code>setHttpClient()</code> позволяет установить HTTP-клиент,
- отличный от принятого по умолчанию.
- </para>
- <para>
- <code>setHttpClient()</code> может быть полезен при
- unit-тестировании. При совместном использовании с
- <classname>Zend_Http_Client_Adapter_Test</classname> можно имитировать
- удаленные сервисы для тестирования. В качестве примера реализации
- рассмотрите unit-тесты для <classname>Zend_XmlRpc_Client</classname>,
- входящие в поставку Zend Framework.
- </para>
- </sect2>
- </sect1>
- <!--
- vim:se ts=4 sw=4 et:
- -->
|