Ian P. Christian's Personal Blog Random witterings from pookey

23Mar/091

Using the ‘classmap’ with SOAP in PHP

I've recently done a little bit of SOAP work whilst spec'ing out a project for work - and I noticed that the PHP manual page for SOAP a mention of the 'classmap', which isn't documented so well. I thought I'd put an example here to show it's usage.

Whilst you don't really need to understand specifically what the code below is doing, I shall explain anyway. The code is for locating a service end point for a Postini managed email address. The reason they have a service locator like this is that Postini have many clusters of servers, where each cluster is physically separate from each other - so to manage an account you need to find out where it is first.

Looking at the WSDL XML, we can see how the types are defined:

...
<xsd:complexType name="GetServiceEndpoint">
   <xsd:sequence>
       <xsd:element name="apiKey" type="xsd:string" />
       <xsd:element name="email" type="xsd:string" />
       <xsd:element name="service" type="tns:service" />
   </xsd:sequence>
</xsd:complexType>
 
<xsd:complexType name="GetServiceEndpointResponse">
   <xsd:sequence>
       <xsd:element name="EndpointURI" minOccurs="0" type="xsd:string" />
   </xsd:sequence>
</xsd:complexType>
 
 
<xsd:simpleType name="service">
   <xsd:restriction base="xsd:string">
      <xsd:enumeration value="v1"/>
      <xsd:enumeration value="v2AutomatedBatch"/>
      <xsd:enumeration value="v2PersonalArchive"/>
      <xsd:enumeration value="v2UserSync"/>
   </xsd:restriction>
</xsd:simpleType>
...

We can also see the operation we are interested in:

  <wsdl:operation name="GetServiceEndpoint">
      <soap:operation soapAction="" style="document"/>
      <wsdl:input name="GetServiceEndpoint"><soap:body use="literal"/></wsdl:input>
      <wsdl:output name="GetServiceEndpointResponse"><soap:body use="literal"/></wsdl:output>
      ...
  </wsdl:operation>

The code below shows me creating the classes we need to support the above. We could improve this by altering the 'setService' method of the GetServiceEndpoint class to ensure the parameter refers to a valid service, as specified in the enumeration in the WSDL. We should also improve this code by adding error handling, but for the purposes of this blog post it is removed.

<?php
 
$endpointResolverApi = 'https://.../dl/api/endpointresolver.wsdl';
$apiKey              = '..key..';
 
class GetServiceEndpointResponse
{
  private $EndpointURI;
 
  public function getEndpountUri()
  {
    return $this->EndpointURI;
  }
}
 
class GetServiceEndpoint
{
  private $apiKey;
  private $email;
  private $service;
 
  public function __construct($key, $email, $service = 'v2AutomatedBatch')
  {
    $this->apiKey  = $key;
    $this->email   = $email;
    $this->service = $service;
  }
 
  public function setApiKey($key)
  {
    $this->apiKey = $key;
  }
 
  public function getApiKey()
  {
    return $this->apiKey;
  }
 
  public function setEmail($email)
  {
    $this->email = $email;
  }
 
  public function getEmail()
  {
    return $this->email;
  }
 
  public function setService($service)
  {
    $this->service = $service;
  }
 
  public function getService()
  {
    return $this->service;
  }
}
 
 
$client = new SoapClient($endpointResolverApi, array('classmap' => array(
  'GetServiceEndpointResponse' => 'GetServiceEndpointResponse',
  'GetServiceEndpoint' => 'GetServiceEndpoint'
)));
 
 
$q = new GetServiceEndpoint($apiKey, 'pookey@pookey.co.uk');
 
$ret = $client->GetServiceEndpoint($q);
 
var_dump($ret);

As you can see from the output below, the correct object type is returned.

$ php ./test.php 
object(GetServiceEndpointResponse)#3 (1) {
  ["EndpointURI:private"]=>
  string(46) "https://api-s7.postini.com/api2/automatedbatch"
}

One important point to take note, is that if there was a constructor for GetServiceEndpointResponse - it would NOT be called.

Filed under: geek, php Leave a comment
Comments (1) Trackbacks (0)
  1. Great !
    Thanks to your example my call works !
    With this kind of working, parameters of Soap Call function are embedded into the soap function, else, parameters are out of the call …

    Thanks, lots of works avoided !

    K


Leave a comment


No trackbacks yet.