Zend Framework proporciona soporte para consumir servicios remotos
XML-RPC como cliente en el paquete
Zend_XmlRpc_Client. Sus características principales incluyen la
conversión automática de tipos entre PHP y XML-RPC, un objeto proxy de servidor,
y acceso a las capacidades de introspección del servidor.
El constructor de Zend_XmlRpc_Client recibe la
URL del endpoint del servidor XML-RPC remoto como su
primer parámetro. La nueva instancia devuelta puede usarse para llamar a cualquier cantidad
de métodos remotos en ese endpoint.
Para llamar a un método remoto con el cliente XML-RPC, instáncielo
y use el método de instancia call(). El ejemplo de código
que sigue utiliza un servidor XML-RPC de demostración en el sitio web
de Zend Framework. Puede usarlo para pruebas o para explorar los
componentes de Zend_XmlRpc.
Ejemplo 80.1. Llamada a un método XML-RPC
$client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
echo $client->call('test.sayHello');
// hello
El valor XML-RPC devuelto por la llamada al método remoto será automáticamente desmarshalado y convertido al tipo nativo equivalente de PHP. En el ejemplo anterior, se devuelve un String de PHP y está listo para usarse de inmediato.
El primer parámetro del método call() recibe el
nombre del método remoto a llamar. Si el método remoto requiere
algún parámetro, este puede enviarse proporcionando un segundo parámetro
opcional a call() con un Array de
valores a pasar al método remoto:
Ejemplo 80.2. Llamada a un método XML-RPC con parámetros
$client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
$arg1 = 1.1;
$arg2 = 'foo';
$result = $client->call('test.sayHello', array($arg1, $arg2));
// $result is a native PHP type
Si el método remoto no requiere parámetros, este parámetro opcional
puede omitirse o puede pasarse un array() vacío.
El array de parámetros para el método remoto puede
contener tipos nativos de PHP, objetos Zend_XmlRpc_Value,
o una mezcla de ambos.
El método call() convertirá automáticamente la
respuesta XML-RPC y devolverá su tipo nativo equivalente de
PHP. Un objeto Zend_XmlRpc_Response para el valor de retorno
también estará disponible llamando al método getLastResponse()
después de la llamada.
Algunas llamadas a métodos remotos requieren parámetros. Estos se pasan al
método call() de Zend_XmlRpc_Client
como un array en el segundo parámetro. Cada parámetro puede
darse como un tipo nativo de PHP que se convertirá automáticamente,
o como un objeto que representa un tipo XML-RPC específico
(uno de los objetos Zend_XmlRpc_Value).
Los parámetros pueden pasarse a call() como variables
nativas de PHP, es decir, como String,
Integer, Float,
Boolean, Array, u
Object. En este caso, cada tipo nativo de PHP será
detectado automáticamente y convertido a uno de los tipos XML-RPC
según esta tabla:
Tabla 80.1. Conversiones de tipos PHP y XML-RPC
| Tipo nativo de PHP | Tipo XML-RPC |
|---|---|
| integer | int |
| Zend_Crypt_Math_BigInteger | i8 |
| double | double |
| boolean | boolean |
| string | string |
| null | nil |
| array | array |
| associative array | struct |
| object | array |
| Zend_Date | dateTime.iso8601 |
| DateTime | dateTime.iso8601 |
![]() |
¿A qué tipo se convierten los arrays vacíos? |
|---|---|
|
Pasar un array vacío a un método XML-RPC es problemático,
ya que podría representar tanto un array como un struct.
Sin embargo, esto puede llevar a problemas en sí mismo. En primer lugar,
los servidores que no admiten
system.methodSignature registrarán peticiones fallidas
en el log, y
Para deshabilitar la búsqueda por completo, puede llamar al método
$client->setSkipSystemLookup(true);
$result = $client->call('foo.bar', array(array()));
|
Los parámetros también pueden crearse como instancias de Zend_XmlRpc_Value
para especificar un tipo XML-RPC exacto. Las razones principales
para hacer esto son:
Cuando desea asegurarse de que se pasa el tipo de parámetro correcto al procedimiento (por ejemplo, el procedimiento requiere un entero y usted podría obtenerlo de una base de datos como cadena de texto)
Cuando el procedimiento requiere el tipo base64 o dateTime.iso8601 (que no existe como tipo nativo de PHP)
Cuando la conversión automática puede fallar (por ejemplo, si desea pasar un struct XML-RPC vacío como parámetro. Los structs vacíos se representan como arrays vacíos en PHP pero, si proporciona un array vacío como parámetro, se convertirá automáticamente a un array XML-RPC ya que no es un array asociativo)
Hay dos formas de crear un objeto Zend_XmlRpc_Value:
instanciar directamente una de las subclases de Zend_XmlRpc_Value,
o usar el método de fábrica estático
Zend_XmlRpc_Value::getXmlRpcValue().
Tabla 80.2. Objetos Zend_XmlRpc_Value para tipos XML-RPC
| Tipo XML-RPC |
Constante de Zend_XmlRpc_Value |
Objeto Zend_XmlRpc_Value |
|---|---|---|
| int |
Zend_XmlRpc_Value::XMLRPC_TYPE_INTEGER
|
Zend_XmlRpc_Value_Integer |
| i8 |
Zend_XmlRpc_Value::XMLRPC_TYPE_I8
|
Zend_XmlRpc_Value_BigInteger |
| ex:i8 |
Zend_XmlRpc_Value::XMLRPC_TYPE_APACHEI8
|
Zend_XmlRpc_Value_BigInteger |
| 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 |
| nil |
Zend_XmlRpc_Value::XMLRPC_TYPE_NIL
|
Zend_XmlRpc_Value_Nil |
| ex:nil |
Zend_XmlRpc_Value::XMLRPC_TYPE_APACHENIL
|
Zend_XmlRpc_Value_Nil |
| 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 |
![]() |
Conversión automática |
|---|---|
Al construir un nuevo objeto |
Otra forma de llamar a métodos remotos con el cliente XML-RPC es usar el proxy de servidor. Este es un objeto PHP que actúa como proxy de un namespace XML-RPC remoto, haciendo que funcione lo más parecido posible a un objeto nativo de PHP.
Para instanciar un proxy de servidor, llame al método de instancia
getProxy() de Zend_XmlRpc_Client. Esto
devolverá una instancia de Zend_XmlRpc_Client_ServerProxy.
Cualquier llamada a método en el objeto proxy de servidor se reenviará
al remoto, y los parámetros pueden pasarse como en cualquier otro método
de PHP.
Ejemplo 80.3. Proxy del namespace por defecto
$client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
$service = $client->getProxy(); // Proxy the default namespace
$hello = $service->test->sayHello(1, 2); // test.Hello(1, 2) returns "hello"
El método getProxy() recibe un argumento opcional
que especifica qué namespace del servidor remoto se debe usar como proxy. Si no
recibe un namespace, se usará como proxy el namespace por
defecto. En el siguiente ejemplo, se usará como proxy el
namespace 'test':
Ejemplo 80.4. Proxy de cualquier namespace
$client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
$test = $client->getProxy('test'); // Proxy the "test" namespace
$hello = $test->sayHello(1, 2); // test.Hello(1,2) returns "hello"
Si el servidor remoto admite namespaces anidados de cualquier profundidad, estos también pueden usarse a través del proxy de servidor. Por ejemplo, si el servidor del ejemplo anterior tuviera un método test.foo.bar(), podría llamarse como $test->foo->bar().
Pueden producirse dos tipos de errores durante una llamada a un método XML-RPC:
errores de HTTP y fallos de XML-RPC. El
Zend_XmlRpc_Client reconoce cada uno y proporciona la capacidad
de detectarlos y capturarlos de forma independiente.
Si se produce algún error HTTP, como que el servidor
HTTP remoto devuelva un 404 Not Found, se
lanzará una Zend_XmlRpc_Client_HttpException.
Ejemplo 80.5. Manejo de errores HTTP
$client = new Zend_XmlRpc_Client('http://foo/404');
try {
$client->call('bar', array($arg1, $arg2));
} catch (Zend_XmlRpc_Client_HttpException $e) {
// $e->getCode() returns 404
// $e->getMessage() returns "Not Found"
}
Independientemente de cómo se use el cliente XML-RPC, la
Zend_XmlRpc_Client_HttpException se lanzará
siempre que ocurra un error HTTP.
Un fallo XML-RPC es análogo a una excepción de
PHP. Es un tipo especial devuelto por una llamada a un método
XML-RPC que tiene tanto un código de error como un mensaje de error. Los fallos
XML-RPC se manejan de forma diferente según el contexto en que se use el
Zend_XmlRpc_Client.
Cuando se usa el método call() o el objeto
proxy de servidor, un fallo XML-RPC resultará en el lanzamiento de una
Zend_XmlRpc_Client_FaultException.
El código y el mensaje de la excepción se corresponderán directamente con
sus respectivos valores en la respuesta de fallo XML-RPC
original.
Ejemplo 80.6. Manejo de fallos XML-RPC
$client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
try {
$client->call('badMethod');
} catch (Zend_XmlRpc_Client_FaultException $e) {
// $e->getCode() returns 1
// $e->getMessage() returns "Unknown method"
}
Cuando se usa el método call() para realizar la
petición, la Zend_XmlRpc_Client_FaultException se
lanzará en caso de fallo. Un objeto Zend_XmlRpc_Response
que contiene el fallo también estará disponible llamando a
getLastResponse().
Cuando se usa el método doRequest() para realizar la
petición, no se lanzará la excepción. En su lugar, se
devolverá un objeto Zend_XmlRpc_Response
que contendrá el fallo. Esto puede comprobarse con el
método de instancia isFault() de
Zend_XmlRpc_Response.
Algunos servidores XML-RPC admiten los métodos de introspección de facto
bajo el namespace XML-RPC system..
Zend_XmlRpc_Client proporciona soporte especial para servidores con
estas capacidades.
Se puede obtener una instancia de Zend_XmlRpc_Client_ServerIntrospection
llamando al método getIntrospector() de
Zend_XmlRpcClient. Luego puede usarse para realizar operaciones
de introspección en el servidor.
Internamente, el método de instancia call() de
Zend_XmlRpc_Client construye un objeto de petición
(Zend_XmlRpc_Request) y lo envía a otro método,
doRequest(), que devuelve un objeto de respuesta
(Zend_XmlRpc_Response).
El método doRequest() también está disponible para su uso directo:
Ejemplo 80.7. Procesamiento de la petición a la respuesta
$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);
// $client->getLastRequest() returns instanceof Zend_XmlRpc_Request
// $client->getLastResponse() returns instanceof Zend_XmlRpc_Response
Siempre que el cliente realiza una llamada a un método XML-RPC, ya sea por
medio del método call(),
el método doRequest(), o el proxy de servidor, el último objeto de
petición y su objeto de respuesta resultante siempre estarán disponibles
a través de los métodos getLastRequest() y
getLastResponse() respectivamente.
En todos los ejemplos anteriores, nunca se especificó un cliente HTTP.
Cuando este es el caso, se creará una nueva instancia de
Zend_Http_Client con sus opciones por defecto y será
utilizada automáticamente por Zend_XmlRpc_Client.
El cliente HTTP puede obtenerse en cualquier momento con el método
getHttpClient(). Para la mayoría de los casos, el cliente
HTTP por defecto será suficiente. Sin embargo, el método
setHttpClient() permite inyectar una instancia de cliente
HTTP diferente.
El método setHttpClient() es particularmente útil para pruebas unitarias.
Combinado con Zend_Http_Client_Adapter_Test, los servicios
remotos pueden simularse para las pruebas. Consulte las pruebas unitarias de
Zend_XmlRpc_Client para ver ejemplos de cómo hacerlo.
![[Note]](images/note.png)