| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- EN-Revision: 24249 -->
- <!-- Reviewed: no -->
- <sect1 id="zend.xmlrpc.client">
- <title>Zend_XmlRpc_Client</title>
- <sect2 id="zend.xmlrpc.client.introduction">
- <title>Introduction</title>
- <para>
- Zend Framework possède la capacité de consommer des services distants XML-RPC, via
- la classe <classname>Zend_XmlRpc_Client</classname>. Ses caractéristiques principales
- sont la conversion automatique des types entre <acronym>PHP</acronym> et XML-RPC, un objet proxy de
- serveur, et des possibilités d'introspection du serveur.
- </para>
- </sect2>
- <sect2 id="zend.xmlrpc.client.method-calls">
- <title>Appels de méthodes</title>
- <para>
- Le constructeur de <classname>Zend_XmlRpc_Client</classname> reçoit en premier
- paramètre l'URL du serveur XML-RPC distant. L'instance retournée pourra alors être
- utilisée pour appeler n'importe quelle méthode distante.
- </para>
- <para>
- Pour appeler une méthode distante, utilisez la méthode <methodname>call()</methodname> de
- votre instance. Le code suivant montre un exemple avec le serveur XML-RPC du site de
- Zend Framework. Vous pouvez l'utiliser pour tester ou explorer les possibilités des
- composants <classname>Zend_XmlRpc</classname>.
- </para>
- <example id="zend.xmlrpc.client.method-calls.example-1">
- <title>XML-RPC appel de méthode</title>
- <programlisting language="php"><![CDATA[
- $client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
- echo $client->call('test.sayHello');
- // hello
- ]]></programlisting>
- </example>
- <para>
- Le type de la valeur XML-RPC retournée sera automatiquement casté en un type
- compatible <acronym>PHP</acronym>. Dans l'exemple ci-dessus, une <code>string</code> <acronym>PHP</acronym> est retournée et
- immédiatement utilisable.
- </para>
- <para>
- Le premier paramètre de <methodname>call()</methodname> est le nom de la méthode distante à
- appeler. Si celle-ci demande des paramètres, ceux-ci doivent alors être passés via le
- deuxième paramètre de <methodname>call()</methodname>, sous forme de tableau <acronym>PHP</acronym>
- (<code>array</code>) :
- </para>
- <example id="zend.xmlrpc.client.method-calls.example-2">
- <title>XML-RPC appel de méthode avec des paramètres</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 est un type PHP natif
- ]]></programlisting>
- </example>
- <para>
- Le tableau de paramètres peut contenir des types <acronym>PHP</acronym> natifs, des objets
- <classname>Zend_XmlRpc_Value</classname>, ou bien les deux à la fois.
- </para>
- <para>
- La méthode <methodname>call()</methodname> convertira automatiquement la réponse XML-RPC et
- retournera un type <acronym>PHP</acronym> natif valide. Un objet
- <classname>Zend_XmlRpc_Response</classname> pour la valeur de retour sera de même
- disponible, via un appel à <methodname>getLastResponse()</methodname>.
- </para>
- </sect2>
- <sect2 id="zend.xmlrpc.value.parameters">
- <title>Types et conversions</title>
- <para>
- Certaines méthodes distantes requièrent des paramètres. Ceux-ci sont donnés sous
- forme de tableau <acronym>PHP</acronym> à <methodname>call()</methodname>. Chaque paramètre est supposé être un type
- <acronym>PHP</acronym> natif qui sera alors lui-même converti, ou alors un objet représentant un type
- XML-RPC (un objet parmi les <classname>Zend_XmlRpc_Value</classname>).
- </para>
- <sect3 id="zend.xmlrpc.value.parameters.php-native">
- <title>Types PHP natifs comme paramètres</title>
- <para>
- Les paramètres passés à <methodname>call()</methodname> peuvent être d'un type <acronym>PHP</acronym> natif,
- à savoir <code>string</code>, <code>integer</code>, <code>float</code>,
- <code>boolean</code>, <code>array</code>, ou <code>object</code>. Dans ce cas,
- chacun des types sera converti de manière automatique en son type compatible
- XML-RPC, suivant la table suivante :
- </para>
- <table id="zend.xmlrpc.value.parameters.php-native.table-1">
- <title>PHP et XML-RPC, conversions de types</title>
- <tgroup cols="2">
- <thead>
- <row>
- <entry>Type <acronym>PHP</acronym> natif</entry>
- <entry>XML-RPC type</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>integer</entry>
- <entry>int</entry>
- </row>
- <row>
- <entry>Zend_Crypt_Math_BigInteger</entry>
- <entry>i8</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>null</entry>
- <entry>nil</entry>
- </row>
- <row>
- <entry>array</entry>
- <entry>array</entry>
- </row>
- <row>
- <entry>associative array</entry>
- <entry>struct</entry>
- </row>
- <row>
- <entry>object</entry>
- <entry>array</entry>
- </row>
- <row>
- <entry>Zend_Date</entry>
- <entry>dateTime.iso8601</entry>
- </row>
- <row>
- <entry>DateTime</entry>
- <entry>dateTime.iso8601</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <note>
- <title>Comment est casté un tableau vide ?</title>
- <para>
- Fournir un tableau vide à une méthode XML-RPC est problématique, car il
- peut être représenté sous la forme soit d'un tableau, soit d'une structure
- ("struct"). <classname>Zend_XmlRpc_Client</classname> détecte ce genre de
- conditions et fait une requête vers la méthode
- <code>system.methodSignature</code> du serveur pour déterminer le type XML-RPC
- approprié vers le quel casté.
- </para>
- <para>
- Cependant, ceci peut mener malgré tout à des soucis. Premièrement, les
- serveurs qui ne supportent <code>system.methodSignature</code> vont retourner
- une requête de type échec, et <classname>Zend_XmlRpc_Client</classname>
- résultera en un cast de la valeur de type tableau XML-RPC ("array"). De plus,
- ceci sous-entend que tout appel avec des arguments de type tableau entraîneront
- un appel additionnel au serveur distant.
- </para>
- <para>
- Pour désactiver entièrement la recherche, vous pouvez appeler la méthode
- <methodname>setSkipSystemLookup()</methodname> avant de réaliser votre appel XML-RPC
- :
- </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>Objets <classname>Zend_XmlRpc_Value</classname> en tant que
- paramètres</title>
- <para>
- Les paramètres peuvent aussi être des objets
- <classname>Zend_XmlRpc_Value</classname> qui spécifient alors exactement un type
- XML-RPC. Les raisons principales d'utiliser un tel procédé sont : <itemizedlist>
- <listitem>
- <para>
- Lorsque vous voulez être certain du type de paramètre (la méthode
- attend un entier et vous le récupérez sous forme de chaîne de caractères
- depuis une base de données).
- </para>
- </listitem>
- <listitem>
- <para>
- Lorsque la méthode attend un type <code>base64</code> ou
- <code>dateTime.iso8601</code> (ceux-ci n'existant pas nativement dans le
- langage <acronym>PHP</acronym>).
- </para>
- </listitem>
- <listitem>
- <para>
- Lorsque la conversion de types (cast) peut échouer (vous voulez
- passer une valeur XML-RPC vide comme paramètre. Mais les valeurs vides
- en <acronym>PHP</acronym> sont représentés sous forme de tableaux vides, or si vous passez
- un tableau vide à votre méthode <code>call</code>, il va être converti
- en un tableau XML-RPC, comme ce n'est pas un tableau associatif).
- </para>
- </listitem>
- </itemizedlist>
- </para>
- <para>
- Deux manières existent pour créer des objets
- <classname>Zend_XmlRpc_Value</classname> : instanciez une sous-classe
- <classname>Zend_XmlRpc_Value</classname> directement, ou utilisez une fabrique
- ("factory method") telle que
- <methodname>Zend_XmlRpc_Value::getXmlRpcValue()</methodname>.
- </para>
- <table id="zend.xmlrpc.value.parameters.xmlrpc-value.table-1">
- <title>Objets <classname>Zend_XmlRpc_Value</classname> comme types
- XML-RPC</title>
- <tgroup cols="3">
- <thead>
- <row>
- <entry>XML-RPC Type</entry>
- <entry><classname>Zend_XmlRpc_Value</classname> Constante</entry>
- <entry><classname>Zend_XmlRpc_Value</classname> Objet</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>int</entry>
- <entry><constant>Zend_XmlRpc_Value::XMLRPC_TYPE_INTEGER</constant></entry>
- <entry><classname>Zend_XmlRpc_Value_Integer</classname></entry>
- </row>
- <row>
- <entry>i8</entry>
- <entry><constant>Zend_XmlRpc_Value::XMLRPC_TYPE_I8</constant></entry>
- <entry><classname>Zend_XmlRpc_Value_BigInteger</classname></entry>
- </row>
- <row>
- <entry>ex:i8</entry>
- <entry><constant>Zend_XmlRpc_Value::XMLRPC_TYPE_APACHEI8</constant></entry>
- <entry><classname>Zend_XmlRpc_Value_BigInteger</classname></entry>
- </row>
- <row>
- <entry>double</entry>
- <entry><constant>Zend_XmlRpc_Value::XMLRPC_TYPE_DOUBLE</constant></entry>
- <entry><classname>Zend_XmlRpc_Value_Double</classname></entry>
- </row>
- <row>
- <entry>boolean</entry>
- <entry><constant>Zend_XmlRpc_Value::XMLRPC_TYPE_BOOLEAN</constant></entry>
- <entry><classname>Zend_XmlRpc_Value_Boolean</classname></entry>
- </row>
- <row>
- <entry>string</entry>
- <entry><constant>Zend_XmlRpc_Value::XMLRPC_TYPE_STRING</constant></entry>
- <entry><classname>Zend_XmlRpc_Value_String</classname></entry>
- </row>
- <row>
- <entry>nil</entry>
- <entry><constant>Zend_XmlRpc_Value::XMLRPC_TYPE_NIL</constant></entry>
- <entry><classname>Zend_XmlRpc_Value_Nil</classname></entry>
- </row>
- <row>
- <entry>ex:nil</entry>
- <entry><constant>Zend_XmlRpc_Value::XMLRPC_TYPE_APACHENIL</constant></entry>
- <entry><classname>Zend_XmlRpc_Value_Nil</classname></entry>
- </row>
- <row>
- <entry>base64</entry>
- <entry><constant>Zend_XmlRpc_Value::XMLRPC_TYPE_BASE64</constant></entry>
- <entry><classname>Zend_XmlRpc_Value_Base64</classname></entry>
- </row>
- <row>
- <entry>dateTime.iso8601</entry>
- <entry><constant>Zend_XmlRpc_Value::XMLRPC_TYPE_DATETIME</constant></entry>
- <entry><classname>Zend_XmlRpc_Value_DateTime</classname></entry>
- </row>
- <row>
- <entry>array</entry>
- <entry><constant>Zend_XmlRpc_Value::XMLRPC_TYPE_ARRAY</constant></entry>
- <entry><classname>Zend_XmlRpc_Value_Array</classname></entry>
- </row>
- <row>
- <entry>struct</entry>
- <entry><constant>Zend_XmlRpc_Value::XMLRPC_TYPE_STRUCT</constant></entry>
- <entry><classname>Zend_XmlRpc_Value_Struct</classname></entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>
- <note>
- <title>Conversion automatique</title>
- <para>
- Lorsque vous créez un objet <classname>Zend_XmlRpc_Value</classname>,
- sa valeur est déterminée par un type <acronym>PHP</acronym>. Celui-ci va être converti vers le
- type désiré en utilisant le cast <acronym>PHP</acronym>. Par exemple si une chaîne de
- caractères est donnée comme valeur à un objet
- <classname>Zend_XmlRpc_Value_Integer</classname>, elle sera alors convertie
- suivant la règle <code>(int)$value</code>.
- </para>
- </note>
- </para>
- </sect3>
- </sect2>
- <sect2 id="zend.xmlrpc.client.requests-and-responses">
- <title>Objet proxy du serveur</title>
- <para>
- Un autre moyen d'appeler des méthodes avec un client XML-RPC est d'utiliser le
- proxy du serveur. C'est un objet <acronym>PHP</acronym> qui proxie un espace de nom XML-RPC, en
- fonctionnant autant que possible comme les objets <acronym>PHP</acronym>.
- </para>
- <para>
- Pour instancier un proxy serveur, appelez <methodname>getProxy()</methodname> de
- <classname>Zend_XmlRpc_Client</classname>. Elle retourne un objet
- <classname>Zend_XmlRpc_Client_ServerProxy</classname>. Tout appel de méthode sur l'objet
- proxy sera proxié vers le serveur XML-RPC, et les paramètres seront utilisés comme pour
- une méthode <acronym>PHP</acronym> banale.
- </para>
- <example id="zend.xmlrpc.client.requests-and-responses.example-1">
- <title>Proxy espace de nom par défaut</title>
- <programlisting language="php"><![CDATA[
- $client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
- $service = $client->getProxy();
- // Proxy l'espace de nom par défaut
- $hello = $service->test->sayHello(1, 2);
- // test.Hello(1, 2) retourne "hello"
- ]]></programlisting>
- </example>
- <para>
- La méthode <methodname>getProxy()</methodname> reçoit un argument optionnel désignant l'espace
- de nom à utiliser par le proxy. Par défaut, il s'agit de l'espace général, voici un
- exemple utilisant un espace de nom <code>test</code> :
- </para>
- <example id="zend.xmlrpc.client.requests-and-responses.example-2">
- <title>Proxy un espace de nom</title>
- <programlisting language="php"><![CDATA[
- $client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
- $test = $client->getProxy('test');
- // Proxy l'espace de nommage "test"
- $hello = $test->sayHello(1, 2);
- // test.Hello(1,2) retourne "hello"
- ]]></programlisting>
- </example>
- <para>
- Si le serveur distant supporte les espaces de noms imbriqués, alors le proxy les
- supportera. Par exemple, si le serveur dans l'exemple ci-dessus acceptait les espaces de
- noms imbriqués, alors sa méthode <code>test.foo.bar()</code> aurait pu être appelée via
- <code>$test->foo->bar()</code>.
- </para>
- </sect2>
- <sect2 id="zend.xmlrpc.client.error-handling">
- <title>Gestion des erreurs</title>
- <para>
- Deux types d'erreurs peuvent être distingués : erreurs <acronym>HTTP</acronym>, ou erreurs XML-RPC.
- L'objet <classname>Zend_XmlRpc_Client</classname> reconnaît ces erreurs et fournit les
- moyens de les repérer et de les gérer.
- </para>
- <sect3 id="zend.xmlrpc.client.error-handling.http">
- <title>Erreurs HTTP</title>
- <para>
- Si une erreur <acronym>HTTP</acronym> survient, par exemple le serveur renvoie un <code>404 Not
- Found</code>, alors une <classname>Zend_XmlRpc_Client_HttpException</classname> sera
- levée.
- </para>
- <example id="zend.xmlrpc.client.error-handling.http.example-1">
- <title>Gérer les erreurs HTTP</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() retourne 404
- // $e->getMessage() retourne "Not Found"
- }
- ]]></programlisting>
- </example>
- <para>
- Quelque soit l'utilisation du client XML-RPC, une
- <classname>Zend_XmlRpc_Client_HttpException</classname> sera systématiquement levée
- lorsqu'une erreur <acronym>HTTP</acronym> de quelque type que ce soit est rencontrée.
- </para>
- </sect3>
- <sect3 id="zend.xmlrpc.client.error-handling.faults">
- <title>Erreurs XML-RPC (Faults)</title>
- <para>
- Une erreur XML-RPC peut être assimilée à une exception en <acronym>PHP</acronym>. C'est un type
- spécial retourné par une des méthodes du client XML-RPC, et ce type contient un
- message, et un code d'erreur. Les erreurs XML-RPC seront gérées différemment en
- fonction du contexte d'utilisation de l'objet
- <classname>Zend_XmlRpc_Client</classname>.
- </para>
- <para>
- Lors de l'utilisation de la méthode <methodname>call()</methodname>, ou de l'objet proxy
- serveur, une erreur XML-RPC aura pour effet de lancer une
- <classname>Zend_XmlRpc_Client_FaultException</classname>. Le code et le message de
- l'exception seront rendus dans leurs valeurs respectives de la réponse
- XML-RPC.
- </para>
- <example id="zend.xmlrpc.client.error-handling.faults.example-1">
- <title>Gérer les erreurs XML-RPC</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() retourne 1
- // $e->getMessage() retourne "Unknown method"
- }
- ]]></programlisting>
- </example>
- <para>
- En utilisant <methodname>call()</methodname>, une exception
- <classname>Zend_XmlRpc_Client_FaultException</classname> sera donc lancée si une
- erreur survient. Un objet <classname>Zend_XmlRpc_Response</classname> contenant
- l'erreur sera de même disponible via la méthode
- <methodname>getLastResponse()</methodname>.
- </para>
- <para>
- Lors de l'utilisation de la méthode <methodname>doRequest()</methodname>, aucune exception
- ne sera levée si une erreur XML-RPC survient. Simplement, l'objet
- <classname>Zend_XmlRpc_Response</classname> retourné contiendra l'erreur.
- Vérifiez-en l'état avec <methodname>isFault()</methodname>.
- </para>
- </sect3>
- </sect2>
- <sect2 id="zend.xmlrpc.client.introspection">
- <title>Introspection du serveur</title>
- <para>
- Certains serveurs XML-RPC supportent l'introspection de leurs méthodes au travers
- de l'espace de noms <code>system.</code> <classname>Zend_XmlRpc_Client</classname>
- fournit un support d'un tel procédé.
- </para>
- <para>
- Une instance de <classname>Zend_XmlRpc_Client_ServerIntrospection</classname> sera
- retournée si vous appelez la méthode <methodname>getIntrospector()</methodname> sur l'objet
- <classname>Zend_XmlRpcClient</classname>.
- </para>
- </sect2>
- <sect2 id="zend.xmlrpc.client.request-to-response">
- <title>De la requête à la réponse</title>
- <para>
- Dans les faits, la méthode <methodname>call()</methodname> de
- <classname>Zend_XmlRpc_Client</classname> fabrique un objet
- <classname>Zend_XmlRpc_Request</classname> et l'envoie à une méthode
- <methodname>doRequest()</methodname>, qui retourne un objet de réponse
- <classname>Zend_XmlRpc_Response</classname>.
- </para>
- <para>La méthode <methodname>doRequest()</methodname> est disponible directement si besoin :</para>
- <example id="zend.xmlrpc.client.request-to-response.example-1">
- <title>Effectuer une requête et récupérer une réponse manuellement</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);
- // $client->getLastRequest() retoure instanceof Zend_XmlRpc_Request
- // $client->getLastResponse() retourne instanceof Zend_XmlRpc_Response
- ]]></programlisting>
- </example>
- <para>
- Lorsqu'une méthode XML-RPC est appelée, quel qu'en soit le moyen,
- (<methodname>call()</methodname>, <methodname>doRequest()</methodname> ou proxy serveur), le dernier objet de
- requête, et son homologue de réponse, seront toujours disponibles, au travers des appels
- à <methodname>getLastRequest()</methodname> et <methodname>getLastResponse()</methodname>.
- </para>
- </sect2>
- <sect2 id="zend.xmlrpc.client.http-client">
- <title>Client HTTP et tests</title>
- <para>
- Dans tous les exemples utilisés sur cette page, nous ne parlons jamais du client
- <acronym>HTTP</acronym>. Lorsque c'est nécessaire, une instance de <classname>Zend_Http_Client</classname>
- sera créée par défaut et injectée dans <classname>Zend_XmlRpc_Client</classname> de
- manière automatique.
- </para>
- <para>
- L'objet client <acronym>HTTP</acronym> peut être récupéré à tout moment grâce à la méthode
- <methodname>getHttpClient()</methodname>. <methodname>setHttpClient()</methodname> permet d'injecter un objet
- <classname>Zend_Http_Client</classname>.
- </para>
- <para>
- <methodname>setHttpClient()</methodname> est particulièrement utilisée pour les tests
- unitaires. Lorsque combinée avec <classname>Zend_Http_Client_Adapter_Test</classname>,
- les services Web peuvent être déguisés (émulés) pour les tests. Voyez les tests
- unitaires de <classname>Zend_XmlRpc_Client</classname> pour des exemples
- concrets.
- </para>
- </sect2>
- </sect1>
|