<?xml version="1.0" encoding="UTF-8"?>
<!-- EN-Revision: 15103 -->
<!-- Reviewed: no -->
<sect1 id="zend.xmlrpc.client">
    <title>Zend_XmlRpc_Client</title>

    <sect2 id="zend.xmlrpc.client.introduction">
        <title>Introdución</title>

        <para>
            Zend Framework provee soporte para consumo remoto para servicios XML-RPC
            como un cliente en el paquete <classname>Zend_XmlRpc_Client</classname>
            . 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.
        </para>

    </sect2>


    <sect2 id="zend.xmlrpc.client.method-calls">
        <title>Method Calls</title>

        <para>
            El constructor de <classname>Zend_XmlRpc_Client</classname> 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>

        <para>
            Para llamar un método remoto con el cliente XML-RPC, instáncealo
            y usa el método de instancia <methodname>call()</methodname> . 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
            <methodname>Zend_XmlRpc</methodname>.
        </para>

        <example id="zend.xmlrpc.client.method-calls.example-1">
            <title>XML-RPC Method Call</title>
             <programlisting language="php"><![CDATA[
$client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');

echo $client->call('test.sayHello');

// hello
]]></programlisting>
        </example>

        <para>
            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 <methodname>string</methodname> PHP
            y está listo para ser usado inmediatamente.
        </para>

        <para>
            El primer parámetro del método <methodname>call()</methodname> 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 <methodname>call()</methodname> con un <methodname>array</methodname> de
            valores para pasar el método remoto:
        </para>

        <example id="zend.xmlrpc.client.method-calls.example-2">
            <title>XML-RPC Method Call with Parameters</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));

// $result es un tipo nativo PHP
]]></programlisting>
        </example>

        <para>
            si el método remoto no requiere parámetros,  este parámetro opcional
            podrá ser excluido o se puede pasar un <methodname>array()</methodname>
            vacío. El array de parámeters para el método repoto puede contener tipos nativos PHPs, objetos <methodname>Zend_XmlRpc_Value</methodname>
            , o una combinación de estos.
        </para>

        <para>
            El método <methodname>call()</methodname> convertirá automáticamente la respuesta
            XML-RPC y devolverá su tipo nativo PHP equivalente. Un objeto
            <methodname>Zend_XmlRpc_Response</methodname> para el valor devuelto también estará
            disponible para llamar el método <methodname>getLastResponse()</methodname>
            después de la llamada.
        </para>
    </sect2>

    <sect2 id="zend.xmlrpc.value.parameters">
        <title>Tipos y Conversiones</title>
        <para>
            Algunas llamadas a métodos remoto requieren parámetros. Éstos son
           dados al método <methodname>call()</methodname> de <classname>Zend_XmlRpc_Client</classname>
            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  <methodname>Zend_XmlRpc_Value</methodname>).
        </para>

        <sect3 id="zend.xmlrpc.value.parameters.php-native">
            <title>Tipos Nativos PHP como Parámetro</title>
            <para>
                Los parámetros pueden ser pasados a <methodname>call()</methodname> como variables
                PHP nativas, ya sea un <methodname>string</methodname>,
                <methodname>integer</methodname>, <methodname>float</methodname>,
                <methodname>boolean</methodname>, <methodname>array</methodname>, o un
                <methodname>object</methodname>. En este caso, cada tipo PHP nativo será
                autodetectado y convertido en uno de los tipos XML-RPC
                de acuerdo con esta tabla:
            </para>

            <table id="zend.xmlrpc.value.parameters.php-native.table-1">
                <title>Tipos de Conversión entre PHP y XML-RPC</title>
                <tgroup cols="2">
                    <thead>
                        <row>
                            <entry>Tipo Nativo PHP</entry>
                            <entry>Tipo 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 asociativo</entry>
                            <entry>struct</entry>
                        </row>
                        <row>
                            <entry>object</entry>
                            <entry>array</entry>
                        </row>
                    </tbody>
                </tgroup>
            </table>

            <note>
                <title>¿A qué tipo se convierten los arrays Vacios?</title>

                <para>
                    Pasar un array vacío a un método XML-RPC es problemático,
                    as it could represent either an array or a struct.
                    <classname>Zend_XmlRpc_Client</classname> detects such conditions and
                    makes a request to the server's
                    <methodname>system.methodSignature</methodname> method to determine the
                    appropriate XML-RPC type to cast to.
                </para>

                <para>
                    However, this in itself can lead to issues. First off,
                    servers that do not support
                    <methodname>system.methodSignature</methodname> will log failed
                    requests, and <classname>Zend_XmlRpc_Client</classname> 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.
                </para>

                <para>
                    To disable the lookup entirely, you can call the
                    <methodname>setSkipSystemLookup()</methodname> method prior to making
                    your XML-RPC call:
                </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><methodname>Zend_XmlRpc_Value</methodname> Objects as Parameters</title>
            <para>
                Parameters may also be created as <methodname>Zend_XmlRpc_Value</methodname>
                instances to specify an exact XML-RPC type.  The primary reasons
                for doing this are:

                <itemizedlist>
                    <listitem>
                        <para>
                            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)
                        </para>
                    </listitem>
                    <listitem>
                        <para>
                            When the procedure requires <methodname>base64</methodname> or
                            <methodname>dateTime.iso8601</methodname> type (which doesn't exists as a
                            PHP native type)
                        </para>
                    </listitem>
                    <listitem>
                        <para>
                            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)
                        </para>
                    </listitem>
                </itemizedlist>
            </para>

            <para>
                There are two ways to create a <methodname>Zend_XmlRpc_Value</methodname>
                object: instantiate one of the <methodname>Zend_XmlRpc_Value</methodname>
                subclasses directly, or use the static factory method
                <methodname>Zend_XmlRpc_Value::getXmlRpcValue()</methodname>.
            </para>

            <table id="zend.xmlrpc.value.parameters.xmlrpc-value.table-1">
                <title><methodname>Zend_XmlRpc_Value</methodname> Objects for XML-RPC Types</title>
                <tgroup cols="3">
                    <thead>
                        <row>
                            <entry>XML-RPC Type</entry>
                            <entry><methodname>Zend_XmlRpc_Value</methodname> Constant</entry>
                            <entry><methodname>Zend_XmlRpc_Value</methodname> Object</entry>
                        </row>
                    </thead>
                    <tbody>
                        <row>
                            <entry>int</entry>
                            <entry><methodname>Zend_XmlRpc_Value::XMLRPC_TYPE_INTEGER</methodname></entry>
                            <entry><methodname>Zend_XmlRpc_Value_Integer</methodname></entry>
                        </row>
                        <row>
                            <entry>double</entry>
                            <entry><methodname>Zend_XmlRpc_Value::XMLRPC_TYPE_DOUBLE</methodname></entry>
                            <entry><methodname>Zend_XmlRpc_Value_Double</methodname></entry>
                        </row>
                        <row>
                            <entry>boolean</entry>
                            <entry><methodname>Zend_XmlRpc_Value::XMLRPC_TYPE_BOOLEAN</methodname></entry>
                            <entry><methodname>Zend_XmlRpc_Value_Boolean</methodname></entry>
                        </row>
                        <row>
                            <entry>string</entry>
                            <entry><methodname>Zend_XmlRpc_Value::XMLRPC_TYPE_STRING</methodname></entry>
                            <entry><methodname>Zend_XmlRpc_Value_String</methodname></entry>
                        </row>
                        <row>
                            <entry>base64</entry>
                            <entry><methodname>Zend_XmlRpc_Value::XMLRPC_TYPE_BASE64</methodname></entry>
                            <entry><methodname>Zend_XmlRpc_Value_Base64</methodname></entry>
                        </row>
                        <row>
                            <entry>dateTime.iso8601</entry>
                            <entry><methodname>Zend_XmlRpc_Value::XMLRPC_TYPE_DATETIME</methodname></entry>
                            <entry><methodname>Zend_XmlRpc_Value_DateTime</methodname></entry>
                        </row>
                        <row>
                            <entry>array</entry>
                            <entry><methodname>Zend_XmlRpc_Value::XMLRPC_TYPE_ARRAY</methodname></entry>
                            <entry><methodname>Zend_XmlRpc_Value_Array</methodname></entry>
                        </row>
                        <row>
                            <entry>struct</entry>
                            <entry><methodname>Zend_XmlRpc_Value::XMLRPC_TYPE_STRUCT</methodname></entry>
                            <entry><methodname>Zend_XmlRpc_Value_Struct</methodname></entry>
                        </row>
                    </tbody>
                </tgroup>
            </table>

            <para>
                <note>
                    <title>Automatic Conversion</title>
                    <para>
                        When building a new <methodname>Zend_XmlRpc_Value</methodname>
                        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 <methodname>Zend_XmlRpc_Value_Integer</methodname>
                        object, it will be converted using
                        <methodname>(int)$value</methodname>.
                    </para>
                </note>
            </para>
        </sect3>
    </sect2>

    <sect2 id="zend.xmlrpc.client.requests-and-responses">
        <title>Server Proxy Object</title>
        <para>
            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.
        </para>

        <para>
            To instantiate a server proxy, call the <methodname>getProxy()</methodname>
            instance method of <classname>Zend_XmlRpc_Client</classname>. This will
            return an instance of <methodname>Zend_XmlRpc_Client_ServerProxy</methodname>.
            Any method call on the server proxy object will be forwarded to
            the remote, and parameters may be passed like any other PHP
            method.
        </para>

        <example id="zend.xmlrpc.client.requests-and-responses.example-1">
            <title>Proxy the Default Namespace</title>
             <programlisting language="php"><![CDATA[
$client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');

$server = $client->getProxy();           // Proxy the default namespace

$hello = $server->test->sayHello(1, 2);  // test.Hello(1, 2) returns "hello"
]]></programlisting>
        </example>

        <para>
            The <methodname>getProxy()</methodname> 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 <methodname>test</methodname> namespace
            will be proxied:
        </para>

        <example id="zend.xmlrpc.client.requests-and-responses.example-2">
            <title>Proxy Any Namespace</title>
             <programlisting language="php"><![CDATA[
$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"
]]></programlisting>
        </example>

        <para>
            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
            <methodname>test.foo.bar()</methodname>, it could be called as
            <methodname>$test-&gt;foo-&gt;bar()</methodname>.
        </para>
    </sect2>


    <sect2 id="zend.xmlrpc.client.error-handling">
        <title>Error Handling</title>
        <para>
            Two kinds of errors can occur during an XML-RPC method call: HTTP
            errors and XML-RPC faults. The <classname>Zend_XmlRpc_Client</classname>
            recognizes each and provides the ability to detect and trap them
            independently.
        </para>

        <sect3 id="zend.xmlrpc.client.error-handling.http">
            <title>HTTP Errors</title>

            <para>
                If any HTTP error occurs, such as the remote HTTP server
                returns a <methodname>404 Not Found</methodname>, a
                <methodname>Zend_XmlRpc_Client_HttpException</methodname> will be thrown.
            </para>

            <example id="zend.xmlrpc.client.error-handling.http.example-1">
                <title>Handling HTTP Errors</title>

                 <programlisting language="php"><![CDATA[
$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"

}
]]></programlisting>
            </example>

            <para>
                Regardless of how the XML-RPC client is used, the
                <methodname>Zend_XmlRpc_Client_HttpException</methodname> will be thrown
                whenever an HTTP error occurs.
            </para>
        </sect3>

        <sect3 id="zend.xmlrpc.client.error-handling.faults">
            <title>XML-RPC Faults</title>

            <para>
                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
                <classname>Zend_XmlRpc_Client</classname> is used.
            </para>

            <para>
                When the <methodname>call()</methodname> method or the server
                proxy object is used, an XML-RPC fault will result in a
                <methodname>Zend_XmlRpc_Client_FaultException</methodname> being thrown.
                The code and message of the exception will map directly to
                their respective values in the original XML-RPC fault
                response.
            </para>

            <example id="zend.xmlrpc.client.error-handling.faults.example-1">
                <title>Handling XML-RPC Faults</title>

                 <programlisting language="php"><![CDATA[
$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"

}
]]></programlisting>
            </example>

            <para>
                Cuando el método <methodname>call()</methodname> es usado para realizar la
                petición, <methodname>Zend_XmlRpc_Client_FaultException</methodname> será
				lanzado como error. Un objeto <methodname>Zend_XmlRpc_Response</methodname> conteniendo
				el error estará disponible llamando a
                <methodname>getLastResponse()</methodname>.
            </para>

            <para>
                Cuando el método <methodname>doRequest()</methodname> sea usado para realizar una
				petición, no lanzará una excepción. En vez de eso, devolverá un objeto
				<methodname>Zend_XmlRpc_Response</methodname> que contendrá el error.
				Esto puede comprobarse con
                <methodname>isFault()</methodname> método instancia de
                <methodname>Zend_XmlRpc_Response</methodname>.
            </para>
        </sect3>

    </sect2>

    <sect2 id="zend.xmlrpc.client.introspection">
        <title>Server Introspection</title>
        <para>
            Some XML-RPC servers support the de facto introspection methods under the XML-RPC
            <methodname>system.</methodname> namespace.  <classname>Zend_XmlRpc_Client</classname> provides special
            support for servers with these capabilities.
        </para>

        <para>
            A <methodname>Zend_XmlRpc_Client_ServerIntrospection</methodname> instance may be retrieved by calling
            the <methodname>getIntrospector()</methodname> method of <methodname>Zend_XmlRpcClient</methodname>.  It can
            then be used to perform introspection operations on the server.
        </para>
    </sect2>

    <sect2 id="zend.xmlrpc.client.request-to-response">
        <title>From Request to Response</title>
        <para>
            Under the hood, the <methodname>call()</methodname> instance method of <classname>Zend_XmlRpc_Client</classname>
            builds a request object (<methodname>Zend_XmlRpc_Request</methodname>) and sends it to another method,
            <methodname>doRequest()</methodname>, that returns a response object (<methodname>Zend_XmlRpc_Response</methodname>).
        </para>

        <para>
            The <methodname>doRequest()</methodname> method is also available for use directly:
        </para>

        <example id="zend.xmlrpc.client.request-to-response.example-1">
            <title>Processing Request to Response</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() returns instanceof Zend_XmlRpc_Request
// $server->getLastResponse() returns instanceof Zend_XmlRpc_Response
]]></programlisting>
        </example>

        <para>
            Whenever an XML-RPC method call is made by the client through any
            means, either the <methodname>call()</methodname> method,
            <methodname>doRequest()</methodname> method, or server proxy, the last request
            object and its resultant response object will always be available
            through the methods <methodname>getLastRequest()</methodname> and
            <methodname>getLastResponse()</methodname> respectively.
        </para>
    </sect2>

    <sect2 id="zend.xmlrpc.client.http-client">
        <title>HTTP Client and Testing</title>

        <para>
            In all of the prior examples, an HTTP client was never specified.
            When this is the case, a new instance of
            <methodname>Zend_Http_Client</methodname> will be created with its default
            options and used by <classname>Zend_XmlRpc_Client</classname> automatically.
        </para>

        <para>
            The HTTP client can be retrieved at any time with the
            <methodname>getHttpClient()</methodname> method. For most cases, the default
            HTTP client will be sufficient. However, the
            <methodname>setHttpClient()</methodname> method allows for a different HTTP
            client instance to be injected.
        </para>

        <para>
            The <methodname>setHttpClient()</methodname> is particularly useful for unit testing.  When combined
            with the <classname>Zend_Http_Client_Adapter_Test</classname>, remote services can be mocked
            out for testing.  See the unit tests for <classname>Zend_XmlRpc_Client</classname> for examples
            of how to do this.
        </para>
    </sect2>

</sect1>
<!--
vim:se ts=4 sw=4 et:
-->
