Files
doc-fr/reference/sca/examples.xml
Damien Seguy 1476597ce0 initial transalation
git-svn-id: https://svn.php.net/repository/phpdoc/fr/trunk@274693 c90b9560-bf6c-de11-be94-00142212c4b1
2009-01-27 08:51:20 +00:00

1203 lines
40 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision: 1.1 $ -->
<!-- EN-Revision: 1.2 Maintainer: dams Status: ready -->
<!-- Reviewed: no -->
<chapter xml:id="sca.examples" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
&reftitle.examples;
<para>
Les exemples de la section suivante illustrent différents aspects de
PHP pour SCA :
</para>
<!-- {{{ itemizedlist of examples -->
<itemizedlist>
<listitem>
<para>
Comment les annotations PHP peuvent être utilisées pour
définir des classes PHP comme des composants SCA et comment
les annotations sont utilisées pour définir des services.
</para>
</listitem>
<listitem>
<para>
Comment les composants SCA peuvent être exposés comme services Web.
</para>
</listitem>
<listitem>
<para>
Comment un composant SCA peut utiliser un service Web, qu'il soit
fournit par un autre composant SCA ou par un autre service qui n'a
pas de rapport avec SCA.
</para>
</listitem>
<listitem>
<para>
Comment un composant SCA peut appeler un autre composant SCA localement,
avec le même processus et la même pile d'appels.
</para>
</listitem>
<listitem>
<para>
Comment un script client qui n'est pas un composant SCA peut
utiliser la fonction <function>getService</function> pour obtenir
un proxy d'accès à un composant SCA.
</para>
</listitem>
<listitem>
<para>
Comment des structures de données telles que Adresses, ou Commandes
sont représentées comme des Service Data Objects (SDO), et gérées.
</para>
</listitem>
<listitem>
<para>
Comment des composants SCA sont déployés, et en particulier, comment
et quand des fichiers WSDL sont générés pour un service.
</para>
</listitem>
<listitem>
<para>
Comment les paramètres sont toujours passés par valeur (et non par
référence), entre les composants, même si les appels sont locaux.
Cela garantit que la sémantique de l'appel ne change pas, en fonction
de l'emplacement du composant.
</para>
</listitem>
<listitem>
<para>
Comment les paramètres de position d'un service sont supportés,
quand le WSDL sous-jacent est un document littéral, et qui ne supporte
que des paramètres nommés.
</para>
</listitem>
<listitem>
<para>
Comment les exceptions métier et d'exécution sont gérées.
</para>
</listitem>
</itemizedlist>
<!-- }}} -->
<!-- {{{ Section Structure -->
<section xml:id="SCA.examples.structure">
<title>La structure d'un composant de service</title>
<para>
Un composant de service est implémenté sous forme de classe.
Pour l'identifier, il doit contenir une annotation
<literal>@service</literal>. L'exécutable SCA
va utiliser le nom du fichier de script pour déterminer le nom
du composant, par convention. La classe et le fichier de script
doivent donc porter le même nom.
</para>
<para>
Les composants PHP SCA doivent toujours exposer un service, et il n'y a
aucun moyen pour un composant d'être appelé autrement que comme le
résultat d'un service Web, ou bien directement par un autre composant
ou un script. Pour cette raison, un composant PHP SCA valide va toujours
contenir une annotation <literal>@service</literal> et au moins une
méthode publique.
</para>
<para>
Chaque composant SCA requiert que le script SCA.php soit inclus. En plus
de contenir la définition de la classe SCA, ce script contient du code PHP
qui est exécuté à chaque appel, et qui est responsable du comportement
général du composant.
</para>
<caution>
<para>
Il est très important que les autres inclusions de votre script
interviennent avant celle du fichier SCA.php. S'il y a des inclusions
après SCA.php, ils ne seront pas pris en compte lorsque l'exécutable
SCA traitera votre classe.
</para>
</caution>
<para>
L'exemple ci-dessous montre la structure générale.
</para>
<para>
<example>
<title> Structure d'un composant SCA pour PHP</title>
<programlisting role="php">
<![CDATA[
<?php
// les inclusions
include "SCA/SCA.php";
/**
* @service
*/
class ConvertedStockQuote {
// variables, logique métier, inclusion d'au moins une méthode publique
}
?>
]]>
</programlisting>
</example>
</para>
</section>
<!-- }}} -->
<!-- {{{ Section Proxies -->
<section xml:id="SCA.examples.proxies">
<title> Obtention d'un proxy pour un autre composant de service </title>
<para>
Un composant SCA peut appeler le service proposé par un autre composant
SCA. Le service que fournit un composant est constitué de toutes ses
méthodes publiques. SCA pour PHP propose deux méthodes pour que les
composants s'appellent les uns les autres : soit localement (i.e., via
le même exécutable PHP, et avec la même pile), ou bien à distance, via
un service Web.
</para>
<para>
Afin qu'un composant en appelle un autre, le composant d'appel a besoin
d'un proxy jusqu'au composant appelé. Ce proxy est généralement fourni
sous forme de variable dans le composant appelant, même si les proxy
peuvent être obtenu via la fonction <function>SCA::getService()</function>.
Quand un composant est construit, les proxy sont constitués pour toute
variable d'instance qui fait référence à un autre composant, et ces proxy
sont injectés dans les variables. Les proxy sont toujours utilisé, que
le composant soit distant ou locale, afin de propose une interface
d'appel identique, quelque soit la localisation des composants.
Les proxy savent comment localiser un composant, et leur passer les
appels.
</para>
<para>
Les variables d'instance qui sont destinées à contenir les proxy sont
identifiées par deux annotations PHPDocumentor :
<literal>@reference</literal> et <literal>@binding</literal>.
Ces deux annotations sont rangées dans la section de documentation d'une
classe, tel que le montre le code ci-dessous.
</para>
<para>
L'annotation <literal>@reference</literal> pour une variable d'instance
indique que la variable doit être initialisée avec un proxy de composant.
</para>
<para>
L'annotation <literal>@binding</literal> prend deux formes :
<literal>@binding.php</literal> et <literal>@binding.soap</literal>.
Elles indiquent que le proxy est soit local, soit un service Web
distant, respectivement. Pour les deux <literal>@binding.php</literal>
et <literal>@binding.soap</literal>, l'annotation indique l'URI cible.
</para>
<para>
A ce moment, avec la méthode de spécification des dépendances via
les annotations, le seul moyen de modifier la cible d'une référence
est de modifier l'annotation dans le composant.
</para>
<para>
Dans notre exemple, la variable <varname>$exchange_rate</varname>
est initialisée avec un proxy vers le composant ExchangeRate,
à chaque fois qu'une instance de ConvertedStockQuote est construite.
</para>
<para>
<example>
<title> Obtention d'un proxy pour une classe PHP locale </title>
<programlisting role="php">
<![CDATA[
<?php
/**
* Le service de change à utiliser
*
* @reference
* @binding.php ../ExchangeRate/ExchangeRate.php
*/
public $exchange_rate;
?>
]]>
</programlisting>
</example>
</para>
<para>
Pour <literal>@binding.php</literal>, l'URI identifie la localisation
du script qui contient l'implémentation du composant. Le composant sera
appelé localement. Le service fournit est un jeu de méthodes publiques
dans le composant. L'URI doit être un simple chemin, absolu ou relatif.
Le composant sera chargé avec une fonction <function>include</function>
de PHP, après avoir vérifié que le composant n'est pas chargé, avec
<function>class_exists</function>. Si l'URI est relative, elle est
résolue relativement au composant qui contient l'annotation. Notez que
cela est différent du comportement habituel de PHP, où les scripts
cherchent les fichiers dans l'include_path. Ceci est nécessaire
pour fournir une indépendance de localisation dans les références.
</para>
<para>
Si ce service ExchangeRate était distant, et qu'il était appelé comme un
service Web, seule la ligne <literal>@binding</literal> aurait changé.
Au lieu de donner la localisation d'une classe PHP, il faudrait donner
la localisation d'un fichier WSDL, décrivant un service Web. Dans notre
exemple de composant, ceci est illustré par la seconde référence :
</para>
<para>
<example>
<title> Obtention d'un proxy pour un service Web </title>
<programlisting role="php">
<![CDATA[
<?php
/**
* Le service de cotation des actions à utiliser
*
* @reference
* @binding.soap ../StockQuote/StockQuote.wsdl
*/
public $stock_quote;
?>
]]>
</programlisting>
</example>
</para>
<para>
Le composant StockQuote sera appelé comme un service Web. Dans ce cas,
l'URI du WSDL peut être un simple chemin, ou utiliser un gestionnaire
de flux PHP, et commencer, par exemple, avec <varname>file://</varname>
ou <varname>http://</varname>. Dans l'événement où c'est un simple chemin
de fichiers, il peut être absolu ou relatif, et dans le cas d'un chemin
relatif, il sera résolu relativement au fichier qui contient l'annotation.
Notez que c'est le même comportement que pour
<literal>@binding.php</literal>, et que c'est différent
du comportement habituel de PHP.
</para>
</section>
<!-- }}} -->
<!-- {{{ Section Calling -->
<section xml:id="SCA.examples.calling">
<title> Appel d'un autre composant de service </title>
<para>
L'exemple ConvertedStockQuote fait aussi appel à des proxy pour
deux composants dont il dépend.
</para>
<para>
<example>
<title> Appels de services </title>
<programlisting role="php">
<![CDATA[
<?php
$quote = $this->stock_quote->getQuote($ticker);
$rate = $this->exchange_rate->getRate($currency);
?>
]]>
</programlisting>
</example>
</para>
<para>
L'appel du service StockQuote est un appel à un service local;
l'appel à ExchangeRate est un appel à un service distant. Notez que ces
deux appels se ressemblent beaucoup, même si l'un est local et l'autre
distant.
</para>
<para>
Les proxy ont été injecté pour s'assurer que les appels à ces
deux composants sont bien les mêmes, quelle que soit leur nature.
Par exemple, le proxy d'un service local fait une copie des arguments,
et ne fait que passer ces copies, afin de s'assurer que les appels
sont bien fait par valeur, comme cela serait le cas dans un service
Web. De même, le proxy d'un service Web prend les arguments dans une
liste à position, et s'assurent qu'ils sont correctement transmis
dans une requête SOAP, puis convertis de nouveau en variable, au retour.
</para>
<para>
Dans l'exemple ci-dessus, <varname>$ticker</varname> et
<varname>$currency</varname> sont clairement des valeurs PHP scalaires.
Les composants peuvent passer des types scalaires, &string;, &integer;,
&float; et &boolean;, mais les structures de données pour les appels de
services sont toujours passés comme Service Data Objects (SDOs).
Une section ultérieur montre comment un composant peut créer un SDO à passer
à un service local, ou distant. La documentation PHP montre comment
manipuler les <link linkend='ref.sdo'>objets SDO</link>.
</para>
</section>
<!-- }}} -->
<!-- {{{ Section nonscascript -->
<section xml:id="SCA.examples.nonSCAscript">
<title>Localisation et appel d'un service, depuis un script qui n'est
pas un composant SCA</title>
<para>
Les composants SCA peuvent obtenir des proxy d'autres composants ou
services qui ne sont pas annotés avec <literal>@reference</literal>,
mais ce n'est pas possible pour un script qui n'est pas lui-même un
composant. Un script client qui n'est pas un client doit utiliser la
fonction statique <function>SCA::getService</function> pour obtenir
un proxy au service, qu'il soit local ou distant. La méthode
<function>getService</function> prendre une URI comme argument.
Typiquement, ceci est la localisation d'un script PHP contenant un
composant, ou un fichier WSDL, et il est utilisé exactement comme
la cible d'une annotation <literal>@binding</literal>, décrite
dans la section précédente : c'est à dire, les URI relatives sont
décrites par rapport au fichier de l'annotation, et non pas
l'include_path de PHP.
</para>
<para>
Par exemple, un script qui a besoin d'obtenir des proxy pour
ExchangeRate et StockQuote mais n'est pas un composant peut utiliser
la fonction <function>SCA::getService</function> comme ceci :
</para>
<para>
<example>
<title> Obtention d'un proxy avec getService </title>
<programlisting role="php">
<![CDATA[
<?php
$exchange_rate = SCA::getService('../ExchangeRate/ExchangeRate.php');
$stock_quote = SCA::getService('../StockQuote/StockQuote.wsdl');
?>
]]>
</programlisting>
</example>
</para>
<para>
Les méthodes d'un service peuvent être appelé sur un proxy ainsi
retourné, tout comme elles peuvent l'être sur un composant.
</para>
<para>
<example>
<title> Faire des appels sur un proxy </title>
<programlisting role="php">
<![CDATA[
<?php
$quote = $stock_quote->getQuote($ticker);
$rate = $exchange_rate->getRate($currency);
?>
]]>
</programlisting>
</example>
</para>
</section>
<!-- }}} -->
<!-- {{{ Section Exposing Webservice Componenent -->
<section xml:id="sca.examples.exposing-webservice">
<title> Exposer un composant comme un service Web </title>
<para>
SCA pour PHP peut générer des fichiers WSDL à partir des annotations
dans un composant, ce qui fait qu'il peut être facilement déployé et
exposé comme un service Web. Pour fournir à SCA les informations dont
il a besoin pour produire le WSDL, il est nécessaire d'ajouter l'annotation
<literal>@binding.soap</literal> dans l'annotation
<literal>@service</literal> et de spécifier les paramètres
et les valeurs de retour avec les annotations <literal>@param</literal> et
<literal>@return.</literal> Ces annotations seront lues quand
le fichier WSDL sera produit, et l'ordre et les types des
paramètres va déterminer le contenu de la section
&lt;schema&gt; du fichier WSDL.
</para>
<para>
SCA pour PHP produit toujours des fichiers WSDL pour les composants
qui exposent des services Web. Notez que cela n'empêche pas les
composants de consommer des services Web qui ne sont pas des
composants SCA, et qui sont documentés avec des fichiers WDSL qui
ne sont pas dans le même format.
</para>
<para>
Les types scalaires qui peuvent être utilisé dans les annotations
<literal>@param</literal> sont les quatres types scalaires communs de PHP :
&boolean;, &integer;, &float; et &string;. Ils sont simplement transformés
en un équivalent au format XML. L'exemple ci-dessous, qui est une
implémentation triviale du service StockQuote avec des appels à
ConvertedStockQuote illustre l'utilisation de &string; et &float;.
</para>
<para>
<example>
<title> Service StockQuote </title>
<programlisting role="php">
<![CDATA[
<?php
include "SCA/SCA.php";
/**
* Implémentation d'un service distant StockQuote Web.
*
* @service
* @binding.soap
*
*/
class StockQuote {
/**
* Lit une cotation pour un symbole
*
* @param string $ticker Le symbole de l'action
* @return float La cotation de l'action
*/
function getQuote($ticker) {
return 80.9;
}
}
?>
]]>
</programlisting>
</example>
</para>
<para>
Un fichier WSDL, semblable au document suivant (mais avec une localisation
de service autre que <literal>'localhost'</literal>, probablement)
sera généré pour le service :
</para>
<para>
<example>
<title> Generated WSDL </title>
<programlisting role="xml">
<![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xsi:type="tDefinitions"
xmlns:tns2="http://StockQuote" xmlns:tns="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns3="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" targetNamespace="http://StockQuote">
<types>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://StockQuote">
<xs:element name="getQuote">
<xs:complexType>
<xs:sequence>
<xs:element name="ticker" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="getQuoteResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="getQuoteReturn" type="xs:float"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
</types>
<message name="getQuoteRequest">
<part name="getQuoteRequest" element="tns2:getQuote"/>
</message>
<message name="getQuoteResponse">
<part name="return" element="tns2:getQuoteResponse"/>
</message>
<portType name="StockQuotePortType">
<operation name="getQuote">
<input message="tns2:getQuoteRequest"/>
<output message="tns2:getQuoteResponse"/>
</operation>
</portType>
<binding name="StockQuoteBinding" type="tns2:StockQuotePortType">
<operation name="getQuote">
<input>
<tns3:body xsi:type="tBody" use="literal"/>
</input>
<output>
<tns3:body xsi:type="tBody" use="literal"/>
</output>
<tns3:operation xsi:type="tOperation" soapAction=""/>
</operation>
<tns3:binding xsi:type="tBinding" transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
</binding>
<service name="StockQuoteService">
<port name="StockQuotePort" binding="tns2:StockQuoteBinding">
<tns3:address xsi:type="tAddress" location="http://localhost/StockQuote/StockQuote.php"/>
</port>
</service>
</definitions>
<!-- this line identifies this file as WSDL generated by SCA for PHP. Do not remove -->
]]>
</programlisting>
</example>
</para>
</section>
<!-- }}} -->
<!-- {{{ Section Deploy -->
<section xml:id="SCA.examples.deploy">
<title> Déploiement d'un composant SCA </title>
<para>
Il n'y pas d'instruction particulière pour déployer un composant PHP SCA.
Il est suffisant de placer le script PHP dans le serveur Web, comme un
autre script PHP. C'est l'exécutable <function>SCA::initComponent</function>
dans le composant qui va l'exécuter correctement, quelque soit la méthode
utilisée, et qui est responsable de proposer la réponse adaptée à la
situation, que ce soit un appel local, Web service ou une requête WDSL.
</para>
</section>
<!-- }}} -->
<!-- {{{ Section Obtaining WSDL -->
<section xml:id="SCA.examples.obtaining-wsdl">
<title>Obtenir le WSDL d'un composant SCA qui offre un service Web</title>
<para>
Les composant SCA qui exposent un service Web (i.e. qui ont une annotation
<literal>@binding.soap</literal>) vont retourner une définition
WSDL en réponse à une requête HTTP avec un paramètre GET "wsdl".
L'approche habituelle pour cela est d'ajouter
"?wsdl" à la fin de l'URL. L'exemple ci-dessous utilise la fonction
<function>file_get_contents</function> pour obtenir un fichier WSDL d'un
service Web, et l'écrit dans un fichier temporaire, avant de demander un
proxy. Vous pouvez évidemment obtenir le fichier WDSL dans votre navigateur,
ou par d'autres moyens, et le sauver vous-mêmes.
</para>
<para>
<example>
<title> WSDL généré </title>
<programlisting role="xml">
<![CDATA[
<?php
$wsdl = file_get_contents('http://www.example.com/Services/Example.php?wsdl');
file_put_contents("service.wsdl",$wsdl); //write the wsdl to a file
$service = SCA::getService('service.wsdl');
?>
]]>
</programlisting>
</example>
</para>
<para>
Note : si le fichier WSDL requiert des importations de xsd, elles
devront être lus séparément.
</para>
</section>
<!-- }}} -->
<!-- {{{ Section Understanding WSDL -->
<section xml:id="SCA.examples.understanding-wsdl">
<title> Comprendre la génération du fichier WSDL </title>
<para>
SCA pour PHP génère un fichier WSDL pour les composants qui contiennent
une annotation <literal>@binding.soap</literal>,
après l'annotation <literal>@service.</literal> Pour générer
le service, SCA analyse la classe, et les annotations
<literal>@param</literal> et <literal>@return</literal>
pour chaque méthode publique, ainsi que les annotations de
<literal>@types</literal> dans le composant. Les
informations des annotations <literal>@param</literal> et
<literal>@return</literal> sont utilisées pour construire
la section &lt;types&gt; du fichier WDSL.
Toutes les annotations <literal>@types</literal> qui
spécifient un schéma distinct engendreront
un élément &lt;import&gt; pour ce schéma dans le WSDL.
</para>
<section xml:id="SCA.examples.understanding-wsdl.location"><!-- {{{ -->
<title> Attribut de localisation pour l'élément &lt;service&gt;</title>
<para>
A la fin du fichier WSDL, l'élément &lt;service&gt; utilise un attribut
de localisation 'location', pour identifier l'URL du service.
Par exemple :
</para>
<para>
<example>
<title> Attribut location </title>
<programlisting role="xml">
<![CDATA[
<service name="ConvertedStockQuote"
...
location="http://localhost/ConvertedStockQuote/ConvertedStockQuote.php"/>
]]>
</programlisting>
</example>
</para>
<para>
Notez que cette localisation est relative à la racine du document
du serveur Web, et ne peut pas être connue à l'avance. Elle ne
peut être résolue que lorsque le composant est mis en place dans
un serveur Web en fonctionnement, lorsque le nom d'hôte et le port
peuvent être connus et placés dans le fichier WDSL. Des informations
de l'URL appelante sont aussi utilisés, ce qui fait que si le WSDL
est produit en réponse à la requête
http://www.example.com:1111/ConvertedStockQuote/ConvertedStockQuote.php?wsdl,
une localisation de
http://www.example.com:1111/ConvertedStockQuote/ConvertedStockQuote.php
sera insérée dans l'attribut.
</para>
</section>
<!-- }}} -->
<section xml:id="SCA.examples.understanding-wsdl.positional-parameters"> <!-- {{{ -->
<title>Inclusion des documents dans le WSDL et paramètres positionnés</title>
<para>
SCA pour PHP produit des fichiers WSDL en incluant les documents et
littéraux. Ce style encadre les paramètres et les valeurs de retour d'une
méthode dans un 'gestionnaire' qui est nommé à partir de la méthode.
L'élément &lt;types&gt; au début du fichier WSDL définit chacun de ces
gestionnaires. Si nous étudions la méthode <function>getQuote</function>
de notre exemple ConvertedStockQuote :
</para>
<para>
<example>
<title> une méthode avec deux arguments </title>
<programlisting role="php">
<![CDATA[
<?php
/**
* Lit une cotation pour une action à partir de son symbole et dans une devise
*
* @param string $ticker Le symbole
* @param string $currency La devise cible
* @return float La valeur de l'action dans la devise demandée
*/
function getQuote($ticker, $currency)
{
$quote = $this->stock_quote->getQuote($ticker);
$rate = $this->exchange_rate->getRate($currency);
return $rate * $quote;
}
?>
]]>
</programlisting>
</example>
</para>
<para>
Pour définir cette méthode, le fichier WSDL va donner des noms
à la méthode et aux paramètres, puis donner au schéma XML le type
des paramètres. La section de type du fichier WSDL produit ressemble
à ceci :
</para>
<para>
<example>
<title> Section types avec paramètres nommés </title>
<programlisting role="xml">
<![CDATA[
<types>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://ConvertedStockQuote">
<xs:element name="getQuote">
<xs:complexType>
<xs:sequence>
<xs:element name="ticker" type="xs:string"/>
<xs:element name="currency" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="getQuoteResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="getQuoteReturn" type="xs:float"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
</types>
]]>
</programlisting>
</example>
</para>
<para>
L'exécutable SCA gère la conversion de la liste des paramètres
positionnés en une requête SOAP, puis de nouveau en liste de
paramètres, au retour de la requête. Pour comprendre où cela est
important, vous pouvez étudier comment PHP qui utiliserait une autre
interface pour faire un appel SOAP devrait construire la liste de
paramètres. Un script PHP utilisant la classe
<classname>SoapClient</classname>, a besoin de passer
les paramètres "ticker" et "currency", peut-être sous forme
de tableau associatif. Pour cela, il faudrait que les appels à des
services Web ou des fonctions locales se fassent avec des interfaces
de programmation différente, et ce n'est pas voulu.
</para>
<para>
Quand SCA génère un fichier WSDL pour un composant SCA, il inclut des
commentaires dans le WDSL qui indique le ce composant est un composant
SCA. Dans ce cas, quand un composant SCA est appelé par un autre composant
via un service Web, l'exécutable SCA prend la liste de paramètres
et assigne les valeurs une à une dans le message SOAP. Par exemple,
un appelle à la méthode <function>getQuote</function> définie ci-dessus
qui passe les valeurs 'IBM' et 'USD' ressemble à ceci :
</para>
<para>
<programlisting role="php">
<![CDATA[
$quote = $remote_service->getQuote('IBM','USD');
]]>
</programlisting>
</para>
<para>
Elle produira un message SOAP qui contient ce code XML :
</para>
<para>
<programlisting role="php">
<![CDATA[
<getQuote>
<ticker>IBM</ticker>
<currency>USD</currency>
</getQuote>
]]>
</programlisting>
</para>
<para>
Dans le composant de réception, l'exécutable SCA prend les paramètres
dans le même ordre, et forme une liste de paramètres positionnés,
en reformant la liste des arguments
('IBM','USD').
</para>
<caution>
<para>
Dans les deux cas, l'exécutable SCA s'appuie sur l'ordre dans lequel
les arguments sont placés dans le message SOAP : cet ordre doit
correspondre à l'ordre d'appel des paramètres dans la fonction.
Cet ordre est finalement défini par l'ordre des annotations
<literal>@param</literal> : il déterminent l'ordre dans lequel
les paramètres apparaissent dans le fichier WSDL, et dans le
message SOAP. Par conséquent, il est essentiel que cet ordre
d'annotations <literal>@param</literal> correspondent aux paramètres
de la méthode publique.
</para>
</caution>
</section>
<!-- }}} -->
</section>
<!-- }}} -->
<section xml:id="SCA.examples.structures"><!-- {{{ -->
<title> Travailler avec des structures de données </title>
<para>
Les composants SCA peuvent échanger les quatre types scalaires
de PHP : &boolean;, &integer;, &float; et &string;, mais aussi passer
des structures de données : SCA utilise les Service Data Objects (SDOs).
Les SDO sont décrits en détails dans
<link linkend='ref.sdo'>les pages SDO</link>
de ce manuel. Les lecteurs habitués aux SDO sauront qu'ils sont
adaptés à la représentation de toutes sortes de données structurées
et semi-structurées, qui sont souvent modélisées en CML, et qui se
linéarises naturellement pour passer entre composants distants.
Les SDO sont actuellement le seul moyen pour échanger des structures
de données. Il n'est pas possible d'échanger des objets PHP ou des
tableaux.
</para>
<para>
L'exécutable SCA s'assure toujours que les données sont passées par valeur,
même dans les appels locaux. Pour cela, SCA copie les SDO dans la
liste de paramètre avant de les passer, comme il le fait pour les valeurs
scalaires.
</para>
<section xml:id="sca.examples.structures.defined"><!-- {{{ -->
<title> Comment les structures de données sont définies par SCA </title>
<para>
Actuellement, le seul mécanisme pour spécifier la localisation d'une
définition de structure de données est de spécifier un type dans un
schéma XML. Cependant, à l'avenir, il est peut être possible de
définir des types d'une autre manière, comme en se basant sur des
classes PHP ou des interfaces, ou encore des tableaux associatifs.
</para>
<para>
Pour illustrer l'utilisation de SDO, voici un nouveau composant.
Le service PortfolioMangement retourne un SDO qui représente un
porte-feuille d'actions, pour un client donné.
</para>
<para>
<example>
<title>Un composant SCA qui utilise des SDO</title>
<programlisting role="php">
<![CDATA[
<?php
include "SCA/SCA.php";
/**
* Gestion de porte-feuille d'un client
*
* @service
* @binding.soap
*
* @types http://www.example.org/Portfolio PortfolioTypes.xsd
*
*/
class PortfolioManagement {
/**
* Lit le porte-feuille d'un client donné.
*
* @param integer $customer_id L'identifiant du client
* @return Portfolio http://www.example.org/Portfolio Le porte-feuille d'actions (symboles et quantités)
*/
function getPortfolio($customer_id) {
// Supposons que nous l'avons lu dans la base de données
$portfolio = SCA::createDataObject('http://www.example.org/Portfolio', 'Portfolio');
$holding = $portfolio->createDataObject('holding');
$holding->ticker = 'AAPL';
$holding->number = 100.5;
$holding = $portfolio->createDataObject('holding');
$holding->ticker = 'INTL';
$holding->number = 100.5;
$holding = $portfolio->createDataObject('holding');
$holding->ticker = 'IBM';
$holding->number = 100.5;
return $portfolio;
}
}
?>
]]>
</programlisting>
</example>
</para>
<para>
L'annotation <literal>@types</literal> :
</para>
<para>
<programlisting role="php">
<![CDATA[
<?php
@types http://www.example.org/Portfolio PortfolioTypes.xsd
?>
]]>
</programlisting>
</para>
<para>
elle indique que les types sont de l'espace de noms
http://www.example.org/Portfolio seront disponibles dans le schéma
PortfolioTypes.xsd. Le fichier WSDL produit va reproduire ces
informations avec une commande d'importation comme ceci :
</para>
<para>
<programlisting role="xml">
<![CDATA[
<xs:import schemaLocation="PortfolioTypes.xsd"
namespace="http://www.example.org/Portfolio"/>
]]>
</programlisting>
</para>
<para>
Ce qui fait que l'URI, absolue ou relative, doit pouvoir être
résolue lors de l'inclusion dans l'attribut schemaLocation.
</para>
</section>
<!-- }}} -->
<section xml:id="sca.examples.structures.creating"><!-- {{{ -->
<title>Création de SDO </title>
<para>
Les lecteurs familiers avec la notion de SDO savent qu'ils doivent
toujours être créés en conformité avec une description de la
structure autorisée (parfois aussi appelé schéma, ou modèle). Et que
au lieu de créer directement le SDO en utilisant l'opérateur
'new', une certaine forme d'usine d'objet doit être utilisée,
mais que, parfois, et notamment pour obtenir le premier objet,
il faut autre chose qu'une usine.
</para>
<para>
En SCA, soit c'est la classe d'exécution ou les proxy, qu'ils soient
locaux ou distants, qui servent d'usine à SDO. Les critères de choix entre
les deux sont décrits dans les prochaines sections.
</para>
<para>
Nous allons passer à un autre exemple pour illustrer la création de SDO,
afin de la passer à un service et pour en recueillir un.
</para>
</section>
<!-- }}} -->
<section xml:id="sca.examples.structures.services"><!-- {{{ -->
<title>Création de SDO à passer à un service</title>
<para>
Un utilisateur de service qui requiert une structure de données
doit utiliser un proxy vers ce service pour avoir une usine à
données qui produira les SDO désirés. Par exemple, supposons
qu'un composant utilise un proxy pour un
service vers un carnet d'adresse AddressBook local.
</para>
<para>
<programlisting role="php">
<![CDATA[
<?php
/**
* @reference
* @binding.local AddressBook.php
*/
$address_book;
?>
]]>
</programlisting>
</para>
<para>
Le composant AddressBook qui doit être utilisé est défini comme ceci :
</para>
<para>
<programlisting role="php">
<![CDATA[
<?php
/**
* @service
* @binding.soap
* @types http://addressbook ../AddressBook/AddressBook.xsd
*/
class AddressBook {
/**
* @param personType $person http://addressbook (un objet de personne)
* @return addressType http://addressbook (un objet d'adress pour l'objet de personne)
*/
function lookupAddress($person) {
...
}
}
?>
]]>
</programlisting>
</para>
<para>
Le composant AddressBook fournit une méthode de service appelée
<function>lookupAddress</function> qui utilise les types du schéma
http://addressbook. La méthode lookupAddress prend une structure
personType et retourne un objet addressType. Les deux types sont
définis dans le schéma addressbook.xsd.
</para>
<para>
Une fois que le composant qui veut utiliser le composant AddressBook
a été construit, de manière à ce que la variable d'instance
<varname>$address_book</varname> contiennent un proxy vers le service,
le composant appelant peut utiliser ce proxy dans
<varname>$address_book</varname> pour créer un SDO de personne,
comme ceci :
</para>
<para>
<programlisting role="php">
<![CDATA[
<?php
$william_shakespeare = $address_book->createDataObject('http://addressbook','personType');
$william_shakespeare ->name = "William Shakespeare";
$address = $address_book->lookupAddress($william_shakespeare);
?>
]]>
</programlisting>
</para>
<para>
Notez que l'utilisation du proxy pour produire un SDO n'est pas limitée
aux seuls composants SCA. Si un service est appelé depuis un script
PHP ordinaire, et que le proxy a été obtenu via la méthode
<function>getService</function> alors la même approche est utilisée.
</para>
<para>
<programlisting role="php">
<![CDATA[
<?php
$address_book = SCA::getService('AddressBook.php');
$william_shakespeare = $address_book->createDataObject('http://addressbook','personType');
?>
]]>
</programlisting>
</para>
</section>
<!-- }}} -->
<section xml:id="sca.examples.structures.services.returning"><!-- {{{ -->
<title> Création d'un SDO à retourner d'un composant </title>
<para>
Un composant qui a besoin de créer un objet de données à retourner
à son appelant ne dispose pas d'un proxy à utiliser comme usine à données,
et dans ce cas, il utilise la méthode statique
<function>createDataObject</function> du fichier
<filename>SCA.php</filename>. Ainsi, si le composant AddressBook
décrit ci-dessus a besoin de créer un objet de type
<classname>addressType</classname> dans l'espace de noms
http://addressbook, il peut le faire comme ceci :
</para>
<para>
<programlisting role="php">
<![CDATA[
<?php
$address = SCA::createDataObject('http://addressbook','addressType');
?>
]]>
</programlisting>
</para>
</section>
<!-- }}} -->
</section>
<!-- }}} -->
<section xml:id="SCA.examples.errorhandling"><!-- {{{ -->
<title> Gestion d'erreurs </title>
<para>
Cette section décrit comment sont gérées les erreurs.
Il y a deux types d'erreur :
</para>
<itemizedlist>
<listitem>
<para>
Les exceptions de l'exécutable SCA sont celles qui signalent
des problèmes dans la gestion de l'exécution des composants,
et dans l'interaction avec les services. Cela peut survenir à cause
de problèmes de configuration réseau.
</para>
</listitem>
<listitem>
<para>
Les exceptions métier sont celles qui sont définies par le programmeur.
Elles étendent la classe PHP Exception, et sont émises puis
interceptées explicitement comme partie intégrante de la logique métier.
</para>
</listitem>
</itemizedlist>
<section xml:id="sca.examples.errorhandling.runtime"><!-- {{{ -->
<title> Gestion des erreurs d'exécution </title>
<para>
Il y a deux types d'erreur SCA :
</para>
<itemizedlist>
<listitem>
<para>
<classname>SCA_RuntimeException</classname> :
elle signale un problème dans ou survenant
dans l'exécutable SCA. Elle peut être émise pour diverses raisons,
et certaines d'entre elles peuvent être indépendantes de la connexion
à un service local ou distant : une erreur dans l'une des annotations
un fichier WSDL ou PHP manquant, etc. Dans le cas des services Web, une
exception <classname>SCA_RuntimeException</classname> peut aussi
être émise si une erreur <classname>SoapFault</classname> a été
émise par un service Web et que le code d'erreur
<classname>SoapFault</classname> indique qu'une
nouvelle tentative a peu de chances d'aboutir.
</para>
</listitem>
<listitem>
<para>
<classname>SCA_ServiceUnavailableException</classname> :
cette classe est une sous-classe de
<classname>SCA_RuntimeException</classname>,
et signale un problème lors de la connexion ou de l'utilisation
d'un service distant, mais une erreur qui peut être dépassée si
une nouvelle tentative est faite. Dans le cas des services Web,
cette exception est émise si une erreur <classname>SoapFault</classname>
est reçue avec un code qui indique qu'une nouvelle tentative
pourrait être couronnée de succès.
</para>
</listitem>
</itemizedlist>
</section>
<!-- }}} -->
<section xml:id="sca.examples.errorhandlilng.business"> <!-- {{{ -->
<title> Gestion des exceptions métier </title>
<para>
Les exceptions métier peuvent être définies et émise par un composant
de manière classique, indépendamment du fait que le service a été
appelé localement ou à distance. L'exécutable SCA n'intercepte pas
les exceptions locales, ce qui fait qu'elles seront acheminées au composant
appelant de manière classique. Si un composant a été appelé comme
service Web, l'exécutable SCA va les intercepter, et s'assurera qu'elles
sont transmises au composant appelant, puis émise à nouveau.
En supposant que le script appelant a une définition de
l'exception métier (c'est à dire qu'il est capable d'inclure
un fichier contenant la définition PHP de l'exception),
la nouvelle exception sera émise avec les mêmes détails que l'originale,
de qui fait que les informations de <function>getLine</function> et
<function>getFile</function> contiendront les indications d'origine de
l'erreur dans les fichiers du service appelé. Cette exception sera passée
via le champ détail de la classe <classname>SoapFault</classname>.
</para>
</section>
<!-- }}} -->
</section>
<!-- }}} -->
</chapter>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"../../../manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->