Working with Data Structures
Working with Data Structures
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');
?>