Travailler avec des structures de données

Les composants SCA peuvent échanger les quatre types scalaires de PHP : booléen, entier, nombre décimal et chaîne de caractères, mais aussi passer des structures de données : SCA utilise les Service Data Objects (SDOs). Les SDO sont décrits en détails dans les pages SDO 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.

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.

Comment les structures de données sont définies par SCA

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.

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é.

Exemple #1 Un composant SCA qui utilise des SDO

<?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;
    }

}
?>

L'annotation @types :

<?php
@types http://www.example.org/Portfolio PortfolioTypes.xsd
?>

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 :

<xs:import schemaLocation="PortfolioTypes.xsd"
                      namespace="http://www.example.org/Portfolio"/>

Ce qui fait que l'URI, absolue ou relative, doit pouvoir être résolue lors de l'inclusion dans l'attribut schemaLocation.

Création de SDO

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.

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.

Nous allons passer à un autre exemple pour illustrer la création de SDO, afin de la passer à un service et pour en recueillir un.

Création de SDO à passer à un service

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.

<?php
/**
 * @reference
 * @binding.local AddressBook.php
 */
$address_book;
?>

Le composant AddressBook qui doit être utilisé est défini comme ceci :

<?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)  {
        ...
    }
}
?>

Le composant AddressBook fournit une méthode de service appelée lookupAddress() 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.

Une fois que le composant qui veut utiliser le composant AddressBook a été construit, de manière à ce que la variable d'instance $address_book contiennent un proxy vers le service, le composant appelant peut utiliser ce proxy dans $address_book pour créer un SDO de personne, comme ceci :

<?php
$william_shakespeare        
$address_book->createDataObject('http://addressbook','personType');
$william_shakespeare ->name "William Shakespeare";
$address                    $address_book->lookupAddress($william_shakespeare);
?>

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 getService() alors la même approche est utilisée.

<?php
$address_book 
SCA::getService('AddressBook.php');
$william_shakespeare $address_book->createDataObject('http://addressbook','personType');
?>

Création d'un SDO à retourner d'un composant

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 createDataObject() du fichier SCA.php. Ainsi, si le composant AddressBook décrit ci-dessus a besoin de créer un objet de type addressType dans l'espace de noms http://addressbook, il peut le faire comme ceci :

<?php
$address 
SCA::createDataObject('http://addressbook','addressType');
?>