SOAP Service

SOAP forms the foundation layer of the Web services stack. It provides a neat way for PHP applications to communicate with each other or with applications written in other languages. PRADO provides TSoapService that makes developing a SOAP server application an extremely easy task.

To use TSoapService, configure it in the application specification like following:

<services>
  <service id="soap" class="System.Web.Services.TSoapService">
    <soap id="stockquote" provider="path.to.StockQuote" />
    <!--
    <soap...other soap service... />
    -->
  </service>
</services>

The example specifies a SOAP service provider named stockquote which implements the getPrice SOAP method in the provider class StockQuote,

class StockQuote
{
	/**
	 * @param string $symbol the symbol of the stock
	 * @return float the stock price
	 * @soapmethod
	 */
	public function getPrice($symbol)
	{
		....return stock price for $symbol
	}
}
Note: TSoapService is based on PHP SOAP extension and thus requires the extension to be installed.

With the above simple code, we already finish a simple SOAP service that allows other applications to query the price of a specific stock. For example, a typical SOAP client may be written as follows to query the stock price of IBM,

$client=new SoapClient('http://path/to/index.php?soap=stockquote.wsdl');
echo $client->getPrice('IBM');

Notice the URL used to construct SoapClient (a class provided by PHP SOAP extension). This is the URL for the WSDL that describes the communication protocol for the SOAP service we just implemented. WSDL is often too complex to be manually written. Fortunately, TSoapService can generate this for us using a WSDL generator. In general, the URL for the automatically generated WSDL in PRADO has the following format:

http://path/to/index.php?SoapServiceID=SoapProviderID.wsdl

In order for the WSDL generator to generate WSDL for a SOAP service, the provider class needs to follow certain syntax. In particular, for methods to be exposed as SOAP methods, a keyword @soapmethod must appear in the phpdoc comment of the method with the following lines specifying method parameters and return value:

  • parameter: @param parameter-type $parameter-name description
  • return value: @return value-type description

Valid parameter and return types include: string, int, boolean, float, array, mixed, etc. You may also specify a class name as the type, which translates into a complex SOAP type. For example, for a complex type Contact

/**
 * Extends TComponent to provide property setter/getter methods
 */
class Contact {
    /**
     * @var string $name
     * @soapproperty
     */
    public $name;

    /**
      * @var string $notes {nillable=1, minOccurs=0, maxOccurs=2}
      * @soapproperty
      */
    public $notes;

    /**
     * @var Address $address
     * @soapproperty
     */
    private $_address;

    public function setAddress($value) {
        $this->_address=$value;
    }

    public function getAddress() {
        if($this->_address===null)
            $this->_address=new Address;
        return $this->_address;
    }
}

class Address{
    /**
     * @var string $city
     * @soapproperty
     */
    public $city;
}

class ContactManager {
    /**
     * @return Contact[] an array of contacts
     * @soapmethod
     */
    function getAllContacts() {
        return array(new Contact);
    }

    /**
     * @return Contact one contact
     * @soapmethod
     */
    function getContact($name) {
        return new Contact;
    }
}

For a complex soap object, the properties of the object are specified with @soapproperty keyword in the property phpdocs. Furthermore, the property's type name must be specified as @var type $name where type is any valid type in mentioned earlier and $name will defined a property name (notice that if your class is a TComponent, you can provide property setter/getter methods).

Optionally, extra attributes (nillable, minOccurs, maxOccurs) can be defined for each property by enclosing definitions into curly brackets and separated by comma like so:

{[attribute1 = value1][, attribute2 = value2], ...}
where the attribute can be one of following:
  • nillable = [0|1|true|false]
  • minOccurs = n; where n>=0
  • maxOccurs = n; where [n>=0|unbounded]

An array of complex objects can also be returned by adding a pair of enclosing square brackets after the type name. For example, to return an array of Contact type, we define @return Contact[] ....

Tip: A very useful tool to test out your web services is the free tool WebServiceStudio 2.0. It can invoke webmethods interactively. The user can provide a WSDL endpoint. On clicking button Get the tool fetches the WSDL, generates .NET proxy from the WSDL and displays the list of methods available. The user can choose any method and provide the required input parameters. The tool requires a MS .NET runtime to be installed.

A similar tool is available for Mac OS X Tiger from http://www.ditchnet.org/soapclient/

TSoapService may be configured and customized in several ways. In the example above, the <soap> element actually specifies a SOAP service using the default TSoapServer implementation. Attributes in <soap> are passed to TSoapServer as its initial property values. For example, the provider attribute initializes the Provider property of TSoapServer. By setting SessionPersistent to be true in <soap> element, the provider instance will persist within the user session. You may develop your own SOAP server class and use it by specifying the class attribute of <soap>.

By default, PHP's soap server will create objects of the type StdClass when objects are received from the client. The soap server can be configured to automatically create objects of certain type objects are received as method parameters. For example, if we have a Soap method that accepts a Contact object as parameter.

/**
 * @param Contact $contact
 * @return boolean true if saved, false otherwise
 * @soapmethod
 */
 function save(Contact $contact)
 {
	return true
 }
The do this, we need to set the ClassMaps property of the TSoapServer in the <soap> tags as a comma separated string of class names that we wish to be automatically converted.
<soap id="contact-manager" provider="path.to.ContactManager"
	ClassMaps="Contact, Address"/>