Working with Data Structures
SCA components can pass and return the four PHP scalar types
boolean, integer, float and string, but to pass or return data
structures, SCA components use Service Data Objects (SDOs). SDOs
are described in much more detail in
the SDO pages of this manual.
Readers familiar with SDOs will know that they are suitable for
representing the sort of structured and semi-structured data that
is frequently modeled in XML, and that they serialize very
naturally for passing between remote components, or in Web
services. SDOs are presently the only supported way to pass and
return data structures. It is not possible to pass or return PHP
objects, or PHP arrays.
The SCA runtime always assures data is passed by-value, even
for local calls. To do this, the SCA runtime copies any SDOs in the
parameter list before passing them on, just as it does for scalar
types.
How data structures are defined to SCA components
Currently the only mechanism for specifying the location of
a data structure definition is by specifying the types in an XML
schema file. However, in the future it may be possible to define
types in other ways, such as based on PHP classes or interfaces, or
based on definitions expressed as associative arrays.
To illustrate the use of SDOs we introduce a new component.
The PortfolioMangement service below returns an SDO
representing a stock portfolio for a given customer.
Example #1 A Component that uses Data Structures
<?php
include "SCA/SCA.php";
/**
* Manage the portfolio for a customer.
*
* @service
* @binding.soap
*
* @types http://www.example.org/Portfolio PortfolioTypes.xsd
*
*/
class PortfolioManagement {
/**
* Get the stock portfolio for a given customer.
*
* @param integer $customer_id The id for the customer
* @return Portfolio http://www.example.org/Portfolio The stock portfolio (symbols and quantities)
*/
function getPortfolio($customer_id) {
// Pretend we just got this from a database
$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;
}
}
?>
The @types annotation:
<?php
@types http://www.example.org/Portfolio PortfolioTypes.xsd
?>
indicates that types in the namespace
http://www.example.org/Portfolio will be found in the schema
file located by the URI PortfolioTypes.xsd. The generated WSDL
would reproduce this information with an import statement as
follows:
<xs:import schemaLocation="PortfolioTypes.xsd"
namespace="http://www.example.org/Portfolio"/>
so the URI, absolute or relative, must be one that can be
resolved when included in the schemaLocation attribute.
Creating SDOs
Readers familiar with SDOs will know that they are always
created according to a description of the permitted structure
(sometimes referred to as the 'schema' or 'model') and that,
rather than creating them directly using 'new', some form of data
factory is needed. Often, an existing data object can be used as the
data factory, but sometimes, and especially in order to get the
first data object, something else must act as the data factory.
In SCA, either the SCA runtime class or the proxies for
services, whether local or remote, can act as the data factories
for SDOs. The choice of which to use, and when, is described in the
next two sections.
We switch to a new example in order to illustrate the creation
of SDOs, both to pass to a service, and to be returned from a service.
Creating an SDO to pass to a service
A caller of a service which requires a data structure to be
passed in to it uses the proxy to the service as the data factory for
the corresponding SDOs. For example, suppose a component makes
use of a proxy for a service provided by a local AddressBook
component.
<?php
/**
* @reference
* @binding.local AddressBook.php
*/
$address_book;
?>
The AddressBook component that it wishes to call is defined
as follows:
<?php
/**
* @service
* @binding.soap
* @types http://addressbook ../AddressBook/AddressBook.xsd
*/
class AddressBook {
/**
* @param personType $person http://addressbook (a person object)
* @return addressType http://addressbook (the address object for the person object)
*/
function lookupAddress($person) {
...
}
}
?>
The AddressBook component provides a service method called
lookupAddress() which uses types from the
http://addressbook namespace. The lookupAddress method takes a
personType data structure and returns an addressType. Both types
are defined in the schema file addressbook.xsd.
Once the component that wishes to use the AddressBook
component has been constructed, so that the
$address_book instance variable contains
a proxy for the service, the calling component can use the proxy in
$address_book to create the person SDO, as
shown below:
<?php
$william_shakespeare = $address_book->createDataObject('http://addressbook','personType');
$william_shakespeare ->name = "William Shakespeare";
$address = $address_book->lookupAddress($william_shakespeare);
?>
Note, the use of the proxy as the means to create the SDO is not
limited to SCA components. If a service is being called from a
general PHP script, and the proxy was obtained with
getService() then the same approach is
used.
<?php
$address_book = SCA::getService('AddressBook.php');
$william_shakespeare = $address_book->createDataObject('http://addressbook','personType');
?>
Creating an SDO to return from a component
A component that needs to create a data object for return to a
caller will not have a proxy to use as a data object, In this case it
uses the
createDataObject() static method on
SCA.php. Hence if the AddressBook
component described above needed to create an object of type
addressType within the namespace
http://addressbook, it might do so as follows:
<?php
$address = SCA::createDataObject('http://addressbook','addressType');
?>