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.
Пример 29.1. Вызов метода XML-RPC
<?php
require_once 'Zend/XmlRpc/Client.php';
$client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
echo $client->call('test.sayHello');
// hello
?>
Значение XML-RPC, возвращаемое при вызове удаленного метода, будет
автоматически приведено к эквивалентному типу в PHP. В примере выше
возвращается строка (тип string в PHP), и она уже
готова к применению.
Первый параметр метода call() принимает имя удаленного
метода, вызов которого требуется. Если удаленный метод требует
каких-либо параметров, то они могут быть переданы методу
call() через второй необязательный параметр в виде
массива значений для последующей передачи удаленному методу:
Пример 29.2. Вызов метода XML-RPC с параметрами
<?php
require_once 'Zend/XmlRpc/Client.php';
$client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
$arg1 = 1.1;
$arg2 = 'foo';
$result = $client->call('test.sayHello', array($arg1, $arg2));
?>
Если удаленный метод не требует параметров, то этот необязательный
параметр можно опустить или передать пустой массив. Массив
параметров для удаленного метода может содержать значения "родного"
для PHP типа, объекты Zend_XmlRpc_Value, либо
и то и другое вместе.
Метод call() будет автоматически преобразовывать ответ
XML-RPC и возвращать его в эквивалентном "родном" для PHP типе.
Кроме этого, можно получить объект Zend_XmlRpc_Response
для возвращенного значения, вызвав метод
getLastResponse() после вызова call().
Некоторых удаленных методов требуют передачи параметров при вызове.
Они предоставляются методу call() объекта
Zend_XmlRpc_Client в виде массива во втором параметре.
Каждый параметр может быть передан в "родном" для PHP типе, который
будет автоматически преобразован, или как объект, представляющий
определенный тип в XML-RPC (один из объектов
Zend_XmlRpc_Value).
Параметры могут передаваться методу call() как
переменные "родного" для PHP типа, это могут быть типы
string, integer, float,
boolean, array или
object. В этом случае каждый из этих типов будет
автоматически определен и преобразован в один из типов XML-RPC
согласно этой таблице:
Параметры могут также создаваться как экземпляры
Zend_XmlRpc_Value для точного указания типа
XML-RPC. Основные причины для этого:
Вы хотите быть уверенными в том, что процедуре передается корректный тип параметра (т.е. процедура требует целочисленное значение, а вы можете получать его из БД в виде строки)
Удаленная процедура требует тип base64
или dateTime.iso8601 (которых нет среди
"родных" для PHP типов).
Автоматическое преобразование может работать неправильно (например, вы хотите передать пустую структуру XML-RPC как параметр. Пустая структура представляется в PHP пустым массивом, но когда вы передаете пустой массив как параметр, он будет преобразован в массив XML-RPC, так как не является ассоциативным массивом)
Есть два пути создания объектов Zend_XmlRpc_Value ―
непосредственное инстанцирование одного из подклассов
Zend_XmlRpc_Value и использование статического
фабричного метода
Zend_XmlRpc_Value::getXmlRpcValue().
Таблица 29.2. Объекты 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 |
![]() |
Автоматическое преобразование |
|---|---|
Когда создается новый объект
|
Другим способом вызова удаленных методов через клиента XML-RPC является использование "заместителя" сервера. Это PHP-объект, который предоставляет интерфейс к удаленному пространству имен XML-RPC, делая работу с ним настолько близкой к работе с обычным объектом в PHP, насколько это возможно.
Для того, чтобы инстанцировать "заместителя" сервера, вызовите
метод getProxy() объекта
Zend_XmlRpc_Client. Любые вызовы методов прокси-объекта
сервера будет перенаправлены к удаленному серверу, параметры могут
передаваться так же, как и для любых других методов в PHP.
Пример 29.3. Прокси-объект к пространству имен по умолчанию
<?php
require_once 'Zend/XmlRpc/Client.php';
$client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
// Создание прокси-объекта к пространству имен по умолчанию
$server = $client->getProxy();
$hello = $server->test->sayHello(1, 2);
// test.Hello(1, 2) возвращает "hello"
?>
Метод getProxy() принимает необязательный аргумент,
указывающий, к какому пространству имен следует создать
прокси-объект. Если этот аргумент не был указан, то то будет
использоваться пространство имен по умолчанию. В следующем примере
используется пространство имен test.
Пример 29.4. Прокси-объект к любому пространству имен
<?php
require_once 'Zend/XmlRpc/Client.php';
$client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
// ... Proxy the "test" namespace
$test = $client->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-сервер
вернул код 404 Not Found, то будет сгенерировано
исключение Zend_XmlRpc_Client_HttpException.
Пример 29.5. Обработка ошибок HTTP
<?php
require_once 'Zend/XmlRpc/Client.php';
$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"
}
?>
Независимо от того, какой клиент XML-RPC используется, всякий
раз, когда происходит ошибка HTTP, генерируется исключение
Zend_XmlRpc_Client_HttpException.
Ошибка XML-RPC аналогична исключению в PHP. Это специальный тип,
возвращаемый при вызове метода XML-RPC и включающий в себя код и
сообщение ошибки. Ошибки XML-RPC обрабатываются по-разному
в зависимости от контекста использования
Zend_XmlRpc_Client.
Если используется метод call() или прокси-объект
сервера, то ошибка XML-RPC приведет к тому, что будет
сгенерировано исключение
Zend_XmlRpc_Client_FaultException. Код и сообщение
исключения будут в точности соответствовать значениям в
возвращенном ответе с сообщением об ошибке.
Пример 29.6. Обработка ошибок XML-RPC
<?php
require_once 'Zend/XmlRpc/Client.php';
$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"
}
?>
Если для выполнения запроса используется метод
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() также доступен для непосредственного
использования:
Пример 29.7. Выполнение запроса
<?php
require_once 'Zend/XmlRpc/Client.php';
$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
?>
Всегда после того, как через клиента был вызван метод XML-RPC (через
методы call(), doRequest() или через
прокси-объект сервера), можно получить объекты последнего запроса и
ответа на него через методы getLastRequest() и
getLastResponse() соответственно.
Ни в одном из предыдущих примеров не указывался HTTP-клиент. В
этом случае создается новый экземпляр Zend_Http_Client
с настройками по умолчанию и автоматически используется
клиентом Zend_XmlRpc_Client.
HTTP-клиент может быть получен в любое время через метод
getHttpClient(). В большинстве случаев достаточно
использование HTTP-клиента по умолчанию. Тем не менее, метод
setHttpClient() позволяет установить HTTP-клиент,
отличный от принятого по умолчанию.
setHttpClient() может быть полезен при
unit-тестировании. При совместном использовании с
Zend_Http_Client_Adapter_Test можно имитировать
удаленные сервисы для тестирования. За примером того, как можно это
реализовать, см. unit-тесты для Zend_XmlRpc_Client.