Zend Framework provee soporte para consumo remoto para servicios
XML-RPC
como un cliente en el paquete
Zend_XmlRpc_Client
. Su mejor
característica es la conversión automática de tipos entre
PHP
y
XML-RPC
, un servidor
de objeto proxy, y acceso a capacidades de instrospección del
servidor.
El constructor de
Zend_XmlRpc_Client
recibe la
URL
del servidor
XML-RPC
como su primer parámetro. La nueva
instacia devuelta puede ser usada para llamar
cualquier número de
métodos remotos en el punto final.
Para llamar un método remoto con el cliente
XML-RPC
, instáncealo y usa el método de
instancia
call()
. El código de ejemplo a
continuación utiliza una demostración en el servidor
XML-RPC
en el sitio web de Zend Framework .
Puede utilizarlo para probar o explorar los
componentes
Zend_XmlRpc
.
Ejemplo 1000. XML-RPC Method Call
$client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc'); echo $client->call('test.sayHello'); // hello
El valor XML-RPC devuelto desde la llamada al método remoto automáticamente será convertida al tipo nativo PHP equivalente . En el ejemplo anterior, es devuelto un string PHP y está listo para ser usado inmediatamente.
El primer parámetro del método
call()
recibe el nombre del método remoto que llamar. Si el método remoto
requiere algún
parámetro, éste puede ser enviado por el suministro
de un segundo, parámetro opcional a
call()
con un
array
de valores para pasar el
método remoto:
Ejemplo 1001. XML-RPC Method Call with Parameters
$client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc'); $arg1 = 1.1; $arg2 = 'foo'; $result = $client->call('test.sayHello', array($arg1, $arg2)); // $result es un tipo nativo PHP
si el método remoto no requiere parámetros, este parámetro
opcional podrá ser excluido o
se puede pasar un
array()
vacío. El array de parámeters
para el método repoto puede contener tipos nativos
PHP
s, objetos
Zend_XmlRpc_Value
, o una combinación
de estos.
El método
call()
convertirá
automáticamente la respuesta
XML-RPC
y devolverá
su tipo nativo
PHP
equivalente. Un objeto
Zend_XmlRpc_Response
para el valor
devuelto también estará disponible para llamar el método
getLastResponse()
después de la
llamada.
Algunas llamadas a métodos remoto requieren parámetros. Éstos son
dados al método
call()
de
Zend_XmlRpc_Client
como un array en el
segundo parámetro. Cada parámetro puede ser dado como un tipo nativo
PHP
, que será convertido automáticamente, o
como un objeto que representa un tipo específico
de
XML-RPC
(uno de los objetos
Zend_XmlRpc_Value
).
Los parámetros pueden ser pasados a
call()
como variables
PHP
nativas, ya sea un
string
,
integer
,
float
,
boolean
,
array
, o un
object
. En este caso, cada tipo
PHP
nativo será autodetectado y convertido en uno de los tipos
XML-RPC
de acuerdo con esta tabla:
Tabla 171. Tipos de Conversión entre PHP y XML-RPC
Tipo Nativo PHP | Tipo XML-RPC |
---|---|
integer | int |
Zend_Crypt_Math_BigInteger | i8 |
double | double |
boolean | boolean |
string | string |
null | nil |
¿A qué tipo se convierten los arrays Vacios?
Passing an empty array to an
XML-RPC
method is problematic,
as it could represent either an array or a struct.
Zend_XmlRpc_Client
detects such conditions and
makes a request to the server's
system.methodSignature
method to determine the
appropriate
XML-RPC
type to cast to.
However, this in itself can lead to issues. First off,
servers that do not
support
system.methodSignature
will log failed
requests, and
Zend_XmlRpc_Client
will resort to
casting the value to an
XML-RPC
array type. Additionally,
this means that any call with array arguments will
result in
an additional call to the remote server.
To disable the lookup entirely, you can call the
setSkipSystemLookup()
method prior to making
your
XML-RPC
call:
$client->setSkipSystemLookup(true); $result = $client->call('foo.bar', array(array()));
Parameters may also be created as
Zend_XmlRpc_Value
instances to specify an exact
XML-RPC
type. The primary reasons
for doing this are:
-
When you want to make sure the correct parameter type is passed to the procedure (i.e. the procedure requires an integer and you may get it from a database as a string)
-
When the procedure requires base64 or dateTime.iso8601 type (which doesn't exists as a PHP native type)
-
When auto-conversion may fail (i.e. you want to pass an empty XML-RPC struct as a parameter. Empty structs are represented as empty arrays in PHP but, if you give an empty array as a parameter it will be auto-converted to an XML-RPC array since it's not an associative array)
There are two ways to create a
Zend_XmlRpc_Value
object: instantiate one of the
Zend_XmlRpc_Value
subclasses directly, or use the static factory method
Zend_XmlRpc_Value::getXmlRpcValue()
.
Tabla 172. Zend_XmlRpc_Value Objects for XML-RPC Types
XML-RPC Type |
Zend_XmlRpc_Value
Constant
|
Zend_XmlRpc_Value
Object
|
---|---|---|
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
|
Automatic Conversion
When building a new
Zend_XmlRpc_Value
object, its value is set by a
PHP
type. The
PHP
type will be converted to the specified type using
PHP
casting. For example, if a string is given as a
value to the
Zend_XmlRpc_Value_Integer
object, it will be converted using
(int)$value
.
Another way to call remote methods with the XML-RPC client is to use the server proxy. This is a PHP object that proxies a remote XML-RPC namespace, making it work as close to a native PHP object as possible.
To instantiate a server proxy, call the
getProxy()
instance method of
Zend_XmlRpc_Client
. This will
return an instance of
Zend_XmlRpc_Client_ServerProxy
.
Any method call on the server proxy object will be forwarded to
the remote, and
parameters may be passed like any other
PHP
method.
Ejemplo 1002. Proxy the Default Namespace
$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"
The
getProxy()
method receives an optional argument
specifying which namespace of the remote server to
proxy. If it
does not receive a namespace, the default namespace will be
proxied. In the
next example, the 'test' namespace
will be proxied:
Ejemplo 1003. Proxy Any 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"
If the remote server supports nested namespaces of any depth, these can also be used through the server proxy. For example, if the server in the example above had a method test.foo.bar() , it could be called as $test->foo->bar() .
Two kinds of errors can occur during an
XML-RPC
method call:
HTTP
errors and
XML-RPC
faults. The
Zend_XmlRpc_Client
recognizes each and provides the ability
to detect and trap them independently.
If any
HTTP
error occurs, such as the remote
HTTP
server returns a
404 Not Found
, a
Zend_XmlRpc_Client_HttpException
will be thrown.
Ejemplo 1004. Handling HTTP Errors
$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" }
Regardless of how the
XML-RPC
client is used, the
Zend_XmlRpc_Client_HttpException
will be thrown
whenever an
HTTP
error occurs.
An
XML-RPC
fault is analogous to a
PHP
exception. It is a special type returned from an
XML-RPC
method
call that has both an error code and an error message.
XML-RPC
faults are handled differently depending on the context of how the
Zend_XmlRpc_Client
is used.
When the
call()
method or the server
proxy object is used, an
XML-RPC
fault will result in a
Zend_XmlRpc_Client_FaultException
being thrown.
The code and message of the exception will map directly to
their
respective values in the original
XML-RPC
fault
response.
Ejemplo 1005. Handling XML-RPC Faults
$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 el método
call()
es usado
para realizar la petición,
Zend_XmlRpc_Client_FaultException
será lanzado como error. Un objeto
Zend_XmlRpc_Response
conteniendo el
error estará disponible llamando a
getLastResponse()
.
Cuando el método
doRequest()
sea
usado para realizar una petición, no lanzará una excepción. En
vez de eso,
devolverá un objeto
Zend_XmlRpc_Response
que contendrá
el error. Esto puede comprobarse con
isFault()
método instancia de
Zend_XmlRpc_Response
.
Some
XML-RPC
servers support the de facto introspection methods
under the
XML-RPC
system.
namespace.
Zend_XmlRpc_Client
provides special support for servers with
these capabilities.
A
Zend_XmlRpc_Client_ServerIntrospection
instance may be
retrieved by calling the
getIntrospector()
method of
Zend_XmlRpcClient
. It can then be used to perform introspection
operations on the server.
Under the hood, the
call()
instance method of
Zend_XmlRpc_Client
builds a request object
(
Zend_XmlRpc_Request
) and sends it to another method,
doRequest()
, that returns a response object
(
Zend_XmlRpc_Response
).
The
doRequest()
method is also available for use directly:
Ejemplo 1006. Processing Request to Response
$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
Whenever an
XML-RPC
method call is made by the client through any
means, either the
call()
method,
doRequest()
method, or server proxy, the last request
object and its resultant response object will
always be available
through the methods
getLastRequest()
and
getLastResponse()
respectively.
In all of the prior examples, an
HTTP
client was never specified.
When this is the case, a new instance of
Zend_Http_Client
will be created with its default
options and used by
Zend_XmlRpc_Client
automatically.
The
HTTP
client can be retrieved at any time with the
getHttpClient()
method. For most cases, the default
HTTP
client will be sufficient. However, the
setHttpClient()
method allows for a different
HTTP
client instance to be injected.
The
setHttpClient()
is particularly useful for unit testing.
When combined with the
Zend_Http_Client_Adapter_Test
, remote
services can be mocked out for testing. See the unit tests for
Zend_XmlRpc_Client
for examples of how to do this.