How do I know how I need to invoke SOAP methods in PHP?

PHP supports SOAP invocations with the built-in SOAP client but it doesn't build any data stubs by default. Instead data binding is achieved using associative arrays. The keys are named as the XML elements or attributes and bind the values into the request structure needed by the service.

Whether an element is made an attribute or child tag depends on the definitions inside the WSDL.

The easiest way to find out how to name things is using Eviware's SoapUI which shows the XML structure of a request that can then be translated manually into an array structure.

Considering the snippet created by SoapUI for "isFilesTaggedWith"

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
	xmlns:lev="http://grid.trendmicro.com/services/level-0">
   <soapenv:Header/>
   <soapenv:Body>
      <lev:isFilesTaggedWith>
         <!--Zero or more repetitions:-->
         <file sha1="289959da899bf03a34dd232ac70205df401098b0"/>
         <file sha1="489959da899bf03a34dd232ac70205df401098b0"/>
         <!--Zero or more repetitions:-->
         <tag>clean</tag>
      </lev:isFilesTaggedWith>
   </soapenv:Body>
</soapenv:Envelope>
				

it translates to the PHP code

$fileIds = array();
foreach ($files as $file)
	$fileIds[] = array("sha1" => sha1_file($file));

$requestVars = array("file" => $fileIds, "tag" => array("clean"));
$results = $soapClient->isFilesTaggedWith($requestVars);
				

I'm getting errors like "not authenticated" or "cannot add source to job". What is wrong?

Some of the WebService implementations are session bound and require that a session cookie is correctly handled inside the SOAP client.

This is particularly important when using SOAP frameworks for client connections. Some of them do not have obvious setups when handling session cookies.

It's important to take care that a session cookie is sent out for the whole site! Some SOAP implementations, however are known to keep sessions per service interface instead of site, when using the default setup options (JAX-WS is one example).

Fixing it for Java & JAX-WS based services:

To make session handling work in JAX-WS there exist in general 2 possible options:

  1. Register a global CookieHandler via
    CookieHandler.setDefault(new CookieManager());
    • Advantage: All connections, SOAP and non-SOAP share the same session.
    • Disadvantage: Multiple threads all share the same session.
  2. Implement a LogicalMessageHandler to intercepts inbound and outbound messages and modifies the HTTP headers accordingly.

    • Advantage: Sessions are bound to the instance. Multiple threads can operate on individual sessions.

Notes: Using SUN's default implementations may not work correctly. A working CookieStore or LogicalMessageHandler can be found in the attached troubleshoot-cookiestore-java.zip.

Fixing it for C# & HttpWebClientProtocol based services:

To make session handling work with generated SOAP clients that derive from the base class HttpWebClientProtocol , simply set the property CookieContainer on the client. (This is comparable to the 2nd solution on JAX-WS)

C# Example:

						CookieContainer cookies = new CookieContainer();

						SourceService sourceService = new SourceService();
						ProcessingService processingService = new ProcessingService();

						// Share the same session between 2 services
						sourceService.CookieContainer = processingService.CookieContainer = cookies;