Zend_XmlRpc_Client Введение Zend Framework поддерживает клиентское использование удаленных XML-RPC сервисов через пакет Zend_XmlRpc_Client. Его основные возможности включают в себя автоматическое преобразование типов между PHP и XML-RPC, прокси-объект сервера и доступ к средствам интроспекции на сервере. Вызов методов Конструктор Zend_XmlRpc_Client принимает URL удаленного XML-RPC сервера в качестве первого параметра. Новый экземпляр класса может использоваться для вызова любых удаленных методов этого сервера. Для вызова удаленного метода через клиентa XML-RPC инстанцируйте его и используйте его метод call(). В примере ниже используется демонстрационный XML-RPC сервер на веб-сайте Zend Framework. Вы можете использовать его для тестирования или изучения компонент Zend_XmlRpc. Вызов метода XML-RPC call('test.sayHello'); // hello ]]> Значение XML-RPC, возвращаемое при вызове удаленного метода, будет автоматически приведено к эквивалентному типу в PHP. В примере выше возвращается строка (тип String в PHP), и она уже готова к применению. Первый параметр метода call() принимает имя удаленного метода, вызов которого требуется. Если удаленный метод требует каких-либо параметров, то они могут быть переданы методу call() через второй необязательный параметр в виде массива значений для последующей передачи удаленному методу: Вызов метода XML-RPC с параметрами call('test.sayHello', array($arg1, $arg2)); // возвращаемый результат имеет "родной" для PHP тип ]]> Если удаленный метод не требует параметров, то этот необязательный параметр можно опустить или передать пустой массив. Массив параметров для удаленного метода может содержать значения "родного" для PHP типа, объекты Zend_XmlRpc_Value, либо и то и другое вместе. Метод call() будет автоматически преобразовывать ответ XML-RPC и возвращать его в эквивалентном "родном" для PHP типе. Кроме этого, можно получить объект Zend_XmlRpc_Response для возвращенного значения, вызвав метод getLastResponse() после вызова call(). Типы и их преобразование Некоторые удаленные методы требуют передачи параметров при вызове. Они передаются методу call() объекта Zend_XmlRpc_Client в виде массива во втором параметре. Любой параметр может быть передан в "родном" для PHP типе, который будет автоматически преобразован в соответствующий тип XML-RPC, или как объект, представляющий определенный тип в XML-RPC (один из объектов Zend_XmlRpc_Value). Параметры в "родном" для PHP типе Параметры могут передаваться методу call() как переменные "родного" для PHP типа, это могут быть типы String, integer, float, Boolean, Array или object. В этом случае каждый из этих типов будет автоматически определен и преобразован в один из типов XML-RPC согласно следующей таблице: Преобразование типов PHP и XML-RPC Тип в PHP Тип в XML-RPC integer int double double boolean boolean string string array array array (ассоциативный) struct object array
Какому типу будет соответствовать пустой массив? Передача пустого массива методу XML-RPC несет в себе потенциальную проблему, т.к. он может быть представлен и массивом, и структурой. Zend_XmlRpc_Client в этом случае делает запрос к методу сервера system.methodSignature для определения требуемого типа аргумента и производит соответствующее преобразование. Но такое решение само по себе тоже может быть источником проблем. Во-первых, сервера, которые не поддерживают метод system.methodSignature, будут журналировать это как ошибочные вызовы, в этом случае Zend_XmlRpc_Client будет производить преобразование значения к типу array в XML-RPC. Кроме того, это приводит к дополнительным вызовам к удаленному серверу в случае передачи аргументов в виде массивов. Для того, чтобы полностью отключить эти вызовы, вы можете вызвать метод setSkipSystemLookup() до собственно запроса к методу XML-RPC: setSkipSystemLookup(true); $result = $client->call('foo.bar', array(array())); ]]>
Параметры в виде объектов Zend_XmlRpc_Value Параметры могут также создаваться как экземпляры Zend_XmlRpc_Value для точного указания типа XML-RPC. Основные причины для этого: Вы хотите быть уверенными в том, что процедуре передается корректный тип параметра (т.е. процедура требует целочисленное значение, а вы можете получать его из БД в виде строки) Удаленная процедура требует тип base64 или dateTime.iso8601 (которых нет среди "родных" для PHP типов). Автоматическое преобразование может работать неправильно (например, вы хотите передать пустую структуру XML-RPC в качестве параметра. Пустая структура представляется в PHP пустым массивом, но если вы передаете пустой массив в качестве параметра, то он преобразовывается в массив XML-RPC, т.к. не является ассоциативным массивом) Есть два способа создания объектов Zend_XmlRpc_Value ― непосредственное инстанцирование одного из подклассов Zend_XmlRpc_Value и использование статического фабричного метода Zend_XmlRpc_Value::getXmlRpcValue(). Объекты Zend_XmlRpc_Value для типов XML-RPC Тип XML-RPC Константа Zend_XmlRpc_Value Объект Zend_XmlRpc_Value int Zend_XmlRpc_Value::XMLRPC_TYPE_INTEGER Zend_XmlRpc_Value_Integer double Zend_XmlRpc_Value::XMLRPC_TYPE_DOUBLE Zend_XmlRpc_Value_Double boolean Zend_XmlRpc_Value::XMLRPC_TYPE_BOOLEAN Zend_XmlRpc_Value_Boolean string Zend_XmlRpc_Value::XMLRPC_TYPE_STRING Zend_XmlRpc_Value_String base64 Zend_XmlRpc_Value::XMLRPC_TYPE_BASE64 Zend_XmlRpc_Value_Base64 dateTime.iso8601 Zend_XmlRpc_Value::XMLRPC_TYPE_DATETIME Zend_XmlRpc_Value_DateTime array Zend_XmlRpc_Value::XMLRPC_TYPE_ARRAY Zend_XmlRpc_Value_Array struct Zend_XmlRpc_Value::XMLRPC_TYPE_STRUCT Zend_XmlRpc_Value_Struct
Автоматическое преобразование Когда создается новый объект Zend_XmlRpc_Value, его значение устанавливается в "родном" для PHP типе. Тип в PHP будет преобразован к определенному типу средствами PHP. Например, если в качестве значения для объекта Zend_XmlRpc_Value_Integer была передана строка, то она будет преобразована через (int)$value.
Прокси-объект сервера Другим способом вызова удаленных методов через клиента XML-RPC является использование "заместителя" сервера. Это PHP-объект, который предоставляет интерфейс к удаленному пространству имен XML-RPC, делая работу с ним максимально близкой к работе с обычным объектом в PHP. Для того, чтобы инстанцировать "заместителя" сервера, вызовите метод getProxy() объекта Zend_XmlRpc_Client. Он вернет объект класса Zend_XmlRpc_Client_ServerProxy. Любые вызовы методов прокси-объекта сервера будет перенаправлены к удаленному серверу, параметры могут передаваться так же, как и для любых других методов в PHP. Прокси-объект к пространству имен по умолчанию getProxy(); $hello = $server->test->sayHello(1, 2); // test.Hello(1, 2) возвращает "hello" ]]> Метод getProxy() принимает необязательный аргумент, указывающий, к какому пространству имен следует создать прокси-объект. Если этот аргумент не был указан, то то будет использоваться пространство имен по умолчанию. В следующем примере используется пространство имен test: Прокси-объект к произвольному пространству имен getProxy('test'); $hello = $test->sayHello(1, 2); // test.Hello(1,2) возвращает "hello" ]]> Если удаленный сервер поддерживает сколько угодно вложенные пространства имен, то они также могут использоваться через прокси-объект сервера. Например, если сервер в примере выше имеет метод test.foo.bar(), то он может вызываться следующим образом: $test->foo->bar(). Обработка ошибок При вызове методов XML-RPC могут могут быть ошибки двух типов: HTTP и XML-RPC. Zend_XmlRpc_Client распознает оба типа, позволяя обнаруживать и отлавливать их независимо друг от друга. Ошибки HTTP Если произошла ошибка HTTP - например, удаленный HTTP-сервер вернул код 404 Not Found, - то будет сгенерировано исключение Zend_XmlRpc_Client_HttpException. Обработка ошибок HTTP call('bar', array($arg1, $arg2)); } catch (Zend_XmlRpc_HttpException $e) { // $e->getCode() возвращает 404 // $e->getMessage() возвращает "Not Found" } ]]> Независимо от того, какой клиент XML-RPC используется, всякий раз, когда происходит ошибка HTTP, генерируется исключение Zend_XmlRpc_Client_HttpException. Ошибки XML-RPC Ошибка XML-RPC аналогична исключению в PHP. Это специальный тип, возвращаемый при вызове метода XML-RPC и включающий в себя код и сообщение ошибки. Ошибки XML-RPC обрабатываются по-разному, в зависимости от контекста использования Zend_XmlRpc_Client. Если используется метод call() или прокси-объект сервера, то ошибка XML-RPC приведет к тому, что будет сгенерировано исключение Zend_XmlRpc_Client_FaultException. Код и сообщение исключения будут в точности соответствовать значениям в возвращенном ответе с сообщением об ошибке. Обработка ошибок XML-RPC call('badMethod'); } catch (Zend_XmlRpc_FaultException $e) { // $e->getCode() возвращает 1 // $e->getMessage() возвращает "Unknown method" } ]]> Если для выполнения запроса используется метод call(), то в случае ошибки будет сгенерировано исключение Zend_XmlRpc_FaultException. Объект Zend_XmlRpc_Response, содержащий возвращенную ошибку, можно также получить через метод getLastResponse(). Если для выполнения запроса используется метод doRequest(), то исключение не генерируется. Вместо этого будет возвращен объект Zend_XmlRpc_Response, содержащий возвращенную XML-RPC ошибку. Проверить, содержит ли объект ошибку, можно через метод isFault() объекта Zend_XmlRpc_Response. Интроспекция сервера Некоторые XML-RPC сервера поддерживают интроспекцию методов под пространством имен system.. Zend_XmlRpc_Client предоставляет специальную поддержку для серверов с этой возможностью. Экземпляр Zend_XmlRpc_Client_ServerIntrospection может быть получен через вызов метода getIntrospector() класса Zend_XmlRpcClient. Далее он может использоваться для выполнения операций интроспекции на сервере. От запроса к ответу Метод call() экземпляра Zend_XmlRpc_Client в процессе выполнения строит объект запроса (Zend_XmlRpc_Request) и передает его другому методу doRequest(), который возвращает объект ответа (Zend_XmlRpc_Response). Метод doRequest() также доступен для непосредственного использования: Выполнение запроса setMethod('test.sayHello'); $request->setParams(array('foo', 'bar')); $client->doRequest($request); // $server->getLastRequest() возвращает экземпляр Zend_XmlRpc_Request // $server->getLastResponse() возвращает экземпляр Zend_XmlRpc_Response ]]> После того, как через клиента был вызван метод XML-RPC (через методы call(), doRequest() или через прокси-объект сервера), всегда можно получить объекты последнего запроса и ответа на него через методы getLastRequest() и getLastResponse() соответственно. HTTP-клиент и тестирование Ни в одном из предыдущих примеров не указывался HTTP-клиент. В этом случае создается новый экземпляр Zend_Http_Client с настройками по умолчанию и автоматически используется клиентом Zend_XmlRpc_Client. HTTP-клиент может быть получен в любое время через метод getHttpClient(). В большинстве случаев достаточно использование HTTP-клиента по умолчанию. Тем не менее, метод setHttpClient() позволяет установить HTTP-клиент, отличный от принятого по умолчанию. setHttpClient() может быть полезен при unit-тестировании. При совместном использовании с Zend_Http_Client_Adapter_Test можно имитировать удаленные сервисы для тестирования. В качестве примера реализации рассмотрите unit-тесты для Zend_XmlRpc_Client, входящие в поставку Zend Framework.