Manuel PHP

Table des matières

Préface
I. Au moment de commencer
II. Installation et configuration
III. Référence du langage
IV. Sécurité
V. Caractéristiques
VI. Référence des fonctions
VII. PHP et le moteur interne Zend
VIII. FAQ : foire Aux Questions
IX. Annexes
Remerciements



CXL. SCA Functions

Introduction

Avertissement
Ce module est EXPERIMENTAL. Cela signifie que le comportement de ces fonctions, leurs noms et, concrètement, TOUT ce qui est documenté ici peut changer dans un futur proche, SANS PREAVIS ! Soyez-en conscient, et utilisez ce module à vos risques et périls.

SCA for PHP makes it possible for a PHP programmer to write reusable components, which can be called in a variety of ways, with an identical interface and with a minimum of fuss. At present components can call each other either locally or via Web services, but in the future it is expected that other ways will be possible. It provides the programmer with a way of doing this which will look as natural as possible in PHP.

SCA components use phpDocumentor-style (see http://www.phpdoc.org/) annotations to declare dependencies on other SCA components or Web services. The SCA for PHP runtime resolves these dependencies at runtime on behalf of the components, and thus allows the PHP programmer to focus on the business logic rather than on locating and obtaining references to dependencies.

The SCA for PHP programming model can be extended to support a number of service types, such as REST and Atompub. However, Web services (more accurately, WSDL defined, SOAP/HTTP services), are the only type currently specified.

Components also use annotations to define the interface which they expose as a service. The SCA for PHP runtime will automatically generate WSDL from these annotations, so that an SCA component is easily exposed as a web service. These annotations are a natural extension to those provided by phpDocumentor. Deploying a Web service can be as simple as placing a PHP component under the document root of a web server.

Components also use annotations to specify data structures (expressed using XML schema complex types) which are then handled using Service Data Objects (SDOs).

A PHP script which is not an SCA component and which contains no annotations can use the services of an SCA component. A PHP script or component can make calls to a web service that is not an SCA component, but using the same system of calls or annotations to obtain a reference.

First we show a single SCA component, ConvertedStockQuote which illustrates many of the features of SCA for PHP. It has one method, getQuote(), which given a stock “ticker” obtains a price quote for that stock, converted to a given currency. We shall be using this example as a basis for explaining the SCA for PHP throughout the rest of this document.

Exemple 1. A sample SCA component

<?php
 
include "SCA/SCA.php";
 
/**
 * Calculate a stock price for a given ticker symbol in a given currency.
 *
 * @service
 * @binding.ws
 */
class ConvertedStockQuote {
 
    /**
     * The currency exchange rate service to use.
     *
     * @reference
     * @binding.php ../ExchangeRate/ExchangeRate.php
     */
    public $exchange_rate;
 
    /**
     * The stock quote service to use.
     *
     * @reference
     * @binding.wsdl ../StockQuote/StockQuote.wsdl
     */
    public $stock_quote;
 
    /**
     * Get a stock quote for a given ticker symbol in a given currency.
     *
     * @param string $ticker The ticker symbol.
     * @param string $currency What currency to convert the value to.
     * @return float The stock value is the target currency.
     */
    function getQuote($ticker, $currency)
    {
        $quote  = $this->stock_quote->getQuote($ticker);
        $rate   = $this->exchange_rate->getRate($currency);
        return  $rate * $quote;
    }
}
?>

In this example, we see that an SCA component is implemented by a script containing a PHP class and includes “SCA.php”. The class contains a mixture of business logic and references to other components or services. In the illustrated getQuote() method there is only business logic, but it relies on the instance variables “$stock_quote” and “$exchange_rate” having been initialized. These refer to two other components and will be initialized by the SCA runtime with proxies for these two services, whenever this component executes. The annotations for these two services show one to be a local component, which will be called within the same PHP runtime, and one to be a remote component which will be called via a SOAP request. This component also exposes the getQuote() method both locally and as a web service, so it in turn can be called either locally or remotely.

Pré-requis

If you want to use SCA to consume or produce Web services then you need PHP 5.2.0 or later, built with the soap extension enabled. If you just want to use local components, and do not wish to use the Web service bindings, then this version of SCA for PHP will also run with PHP 5.1.6.

Installation

SCA is packaged along with SDO in one combined package on PECL. See http://www.php.net/sdo#sdo.installation for installing the SCA_SDO package from PECL. The SCA code must be on the include path of your PHP installation, for example if it is installed as /usr/local/lib/php/SCA, the include_path directive must include /usr/local/lib/php

Exemples

The examples in the subsequent sections illustrate the following aspects of PHP for SCA:

  • How PHP annotations are used to define PHP classes as SCA components, and how annotations are used to define the services.
  • How an SCA component can be exposed as a Web service
  • How an SCA component can consume a Web service, whether provided by another SCA component or by some other service which knows nothing of SCA
  • How an SCA component can call another SCA component locally (within the same process and on the same call stack)
  • How a client script which is not an SCA component can use the getService call to obtain a proxy for an SCA component.
  • How data structures such as Addresses, or Puchase Orders, are represented as Service Data Objects, and handled.
  • How SCA components are deployed, and in particular how and when WSDL is generated for a service.
  • How parameters are always passed by value (and not by reference) between components, even when the calls are local. This ensures that the semantics of a call do not change depending on the location of a component.
  • How positional parameters to a service are supported, even when the underlying WSDL is document literal wrapped, and naturally supports only named parameters.
  • How business and runtime exceptions are handled.

The structure of a Service Component

A service component is implemented by a class. To identify it as a service component, it contains an @service annotation. The SCA runtime will use the file name of the script to determine the component name, by convention. The class and script file must therefore share the same name.

PHP SCA components always expose a service, and there is no way for a component to be invoked other than to be called as a result of a Web service request, or called directly from another component or from a script. For this reason a valid PHP SCA component will always contain an @service annotation and at least one public method.

Each SCA Component requires that the SCA.php script is included. As well as containing the definition of the SCA class, this script contains executable PHP code that will run whenever the script is called, and which will be responsible for making the component behave as needed.

Attention
It is very important that if your file contains other includes, they come before the include for SCA.php. If there are includes after the include for SCA.php, they will not have been processed when the SCA runtime runs your class.

The example below illustrates this overall structure

Exemple 2. The structure of an SCA for PHP component

<?php
 
// any includes
 
include "SCA/SCA.php
 
/**
 * @service
 */
 
class ConvertedStockQuote {
 
       // instance variables, business logic, including at least one public method
 
}
?>  

Obtaining a proxy for another Service Component

One SCA component can call the service provided by another SCA component. The service a component provides is made up of all of its public methods. SCA for PHP currently provides two ways for one component to call another: either locally (i.e. within the same PHP run-time, and on the same call stack) or remotely if the called component exposes a Web service binding.

In order for one component to call another, the calling component needs a proxy for the called component. This proxy is usually provided as an instance variable in the calling component, though proxies can also be obtained with the SCA::getService() call, as we shall see later. When a component is constructed, proxies are constructed for any instance variable which refer to another component, and these proxies are “injected” into the instance variables. Proxies are always used, whether the component is local or remote, in order to provide identical calling behavior between remote and local calls (for example, local calls are made to always pass data by-value). The proxies know how to locate the required component and to pass the calls made on to them.

Instance variables which are intended to hold proxies for services are indicated by the two PHPDocumentor-style annotations, @reference and @binding. Both annotations are placed in the documentation section for a class instance variable, as shown by the code below.

The @reference annotation before an instance variable indicates that that instance variable is to be initialized with a proxy to a component.

The @binding annotation has two forms @binding.php and @@binding.ws, and indicates that the proxy is either for a local component or for a Web service respectively. For both @binding.php and @binding.ws, the annotation gives a target URI.

At the moment, with the annotation-based method of specifying dependencies, the only way to alter the intended target of a reference is to alter the annotation within the component.

In our ConvertedStockQuote example, the “$exchange_rate” instance variable will be initialized with a proxy to the local ExchangeRate component whenever an instance of the ConvertedStockQuote is constructed.

Exemple 3. Obtaining a proxy for a local PHP class

<?php 
   /**
     * The currency exchange rate service to use.
     *
     * @reference
     * @binding.php ../ExchangeRate/ExchangeRate.php
     */
    public $exchange_rate;
?>

For @binding.php, the URI identifies the location of the script containing the implementation of the component. The component will be called locally. The service provided is the set of public methods of the component. The URI must be a simple pathname, either absolute or relative. The component will be loaded with the PHP include directive, after testing to see if it is already loaded with class_exists(). If the URI is a relative path, it is resolved relative to the component containing the annotation. Note that this is different from the normal PHP behaviour where scripts would be looked for along the PHP include_path, This is intended to provide some location-independence for cross-component references.

If this ExchangeRate service were remote and to be called as a Web service, only the @binding line changes. Instead of giving the location of a PHP class, it gives the location of the WSDL describing the web service. In our example component, this is illustrated by the second reference:

Exemple 4. Obtaining a proxy for a web service

<?php
/**
     * The stock quote service to use.
     *
     * @reference
     * @binding.wsdl ../StockQuote/StockQuote.wsdl
     */
    public $stock_quote;
?>

The StockQuote component will be called via a Web service request. In this case the URI for the WSDL can be a simple pathname, or may contain a PHP wrapper and begin, for example, with “file:” or “http:“. In the event that it is a simple pathname, it can be absolute or relative, and if relative will be resolved relative to the component containing the annotation. Note that this is like the behaviour for @binding.php, and different from the normal PHP behaviour where the file would be looked for relative to the PHP current working directory, which would usually be the location of the first script to be called. This behaviour is intended to give consistency across the different bindings and to provide some location-independence for references between components.

Calling another Service Component

The ConvertedStockQuote example also calls the proxies for the two components to which it refers.

Exemple 5. Calling services

<?php
$quote  = $this->stock_quote->getQuote($ticker);
$rate   = $this->exchange_rate->getRate($currency);
?>

The call to the StockQuote service is a call to a local service; the call to the ExchangeRate service is a call to a remote service. Note that the way the call is made looks the same regardless of whether the call is to a local service or a remote one.

The proxies which have been injected ensure that the way calls to components look and behave are the same way regardless of whether they are to a local or remote service, so that components are not sensitive to whether a call is to a local or a remote service. For example, the proxy for a local service takes copies of the arguments and passes only those copies, to ensure that calls are made to be pass-by-value, as they would be for a remote call. Also, the proxy for a remote service takes the arguments from a positional parameter list and ensures they are packaged properly in a SOAP request and converted back to a positional parameter list at the far end.

In the example above, the “$ticker” and “$currency” are clearly PHP scalar types. Components can pass the PHP scalar types string, integer, float and boolean, but data structures on service calls are always passed as Service Data Objects (SDOs). A later section describes how a component can create an SDO to pass on a local or Web service call, or how a component can create an SDO to return. The PHP SDO project documentation describes how to work with the SDO APIs (see the SDO pages.

Locating and calling services from a script which is not an SCA Component

SCA components obtain proxies for other components or services as instance variables annotated with @reference, but this is not possible for a script that is not itself also a component. A client script which is not a component must use the SCA::getService() static method to obtain a proxy for a service, whether local or remote. The getService() method takes a URI as the argument. Typically this is the location of a local PHP script containing a component, or of a wsdl file, and is used in exactly the same way as the targets of the @binding annotations described in the previous section: that is, relative URIs are resolved against the location of the client script and not against the PHP include_path or current working directory.

For example, a script that needed to obtain proxies for the ExchangeRate and StockQuote services but was not a component would use the getService() method as follows:

Exemple 6. Obtaining a proxy using getService

<?php
$exchange_rate = SCA::getService('../ExchangeRate/ExchangeRate.php');
$stock_quote   = SCA::getService('../StockQuote/StockQuote.wsdl');
?>

Methods on services can then be called on the returned proxy, just as they can in a component.

Exemple 7. Making calls on the proxy

<?php
$quote  = $stock_quote->getQuote($ticker);
$rate   = $exchange_rate->getRate($currency);
?>

Exposing a Service Component as a Web service

SCA for PHP can generate WSDL from the annotations within a service component, so that it can be easily deployed and exposed as a Web service. To provide SCA with the information it needs to generate the WSDL, it is necessary to add the annotation @binding.ws under the @service annotation and to specify the parameters and return values of the methods using the @param and @return annotations. These annotations will be read when WSDL is generated, and the order and types of the parameters determine the contents of the <schema> section of the WSDL.

SCA for PHP always generates document/literal wrapped WSDL for components that are exposing a Web service. Note that this does not stop components from consuming Web services which are not SCA components and which are documented with WSDL written in a different style.

The scalar types which can be used in the @param annotation are the four common PHP scalar types: boolean, integer, float and string. These are simply mapped to the XML schema types of the same name in the WSDL. The example below, which is a trivial implementation of the StockQuote service that the ConvertedStockQuote component calls, illustrates string and float types.

Exemple 8. StockQuote Service

<?php
 
include "SCA/SCA.php";
 
/**
 * Scaffold implementation for a remote StockQuote Web service.
 *
 * @service
 * @binding.ws
 *
 */
class StockQuote {
 
    /**
     * Get a stock quote for a given ticker symbol.
     *
     * @param string $ticker The ticker symbol.
     * @return float The stock quote.
     */
    function getQuote($ticker) {
        return 80.9;
  }
}
?>

WSDL much like the following (though with a service location other than ‘localhost’, probably) would be generated from this service:

Exemple 9. Generated WSDL <?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 –>

Deploying an SCA component

There are no special steps needed to deploy a PHP SCA component. It is sufficient to place the component PHP script in its proper place under the web server document root, just like any other PHP script. It is the SCA::initComponent() executable line within each component that will be executed whenever the script is called, and which will be responsible for making the component respond appropriately to Web service calls, local calls, or requests for WSDL.

Obtaining the WSDL for an SCA component offering a Service as a Web service

SCA components that expose a Web service interface (i.e. have an @binding.ws annotation) will return their WSDL definition in response to an HTTP request with a get parameter of “wsdl”. The usual way to obtain this is with “?wsdl” on the end of a URL. The example below uses file_get_contents() to obtain WSDL from a service and writes it to a temporary file before then obtaining a proxy for the service in the usual way. You could of course also obtain the WSDL in a browser, or by some other means, and save the file yourself.

Exemple 10. Generated WSDL

Travail collaboratif

Contribuez, en ajjoutant des elements a cette page de manuel :

Merci de votre aide
L’equipe Php.fr

 


Index | Afficher le texte source | Anciennes révisions | Derniers changements | Connexion
©2007 Wiki Copyright