Well, it turns out that my so-called solution to the Zend_Soap_Server / PHP SoapServer and the dreaded “objects within array encoded as SOAP-ENC:struct” problem was not 100% correct.
The issue is that this part of the response document:
<items enc:itemType="enc:Struct" enc:arraySize="2" xsi:type="enc:Array">
...should look more like this:
<items enc:arrayType="xsd:anyType[2]" xsi:type="enc:Array"$gt;
After six hours of wailing and gnashing of teeth (and a little bit of Googling!), I finally found a solution that should work in most situations.
The solution involves several important facets of Zend_Soap_Autodiscover
, so some code snippets are necessary to demonstrate all the subtleties. The key element to this fix, which is making sure the array of objects is encoded correctly in the PHPDOC section, is applicable to regular PHP SOAP as well. See here for details.
Lets assume that these are the key classes used by our SOAP server:
class RespItem
{
/** @var string */
public $stuff;
}
class PingBack
{
/** @var RespItem[] */
public $items;
}
class Foo
{
/**
* @param string
* @return PingBack
*/
public function ping( $testData )
{
$response = new PingBack();
// Populate $response object with data...
return $response;
}
}
The most important thing to note about the above is the way the array of RespItem
objects is notated in the PingBack
class. If you use the array
key word then you get the enc:itemType="enc:Struct"
behaviour described above. In addition to notating the array
correctly, you also have to use the Zend_Soap_Wsdl_Strategy_ArrayOfTypeComplex
discovery strategy when you instantiate the Zend_Soap_Autodiscover object:
$auto = new Zend_Soap_AutoDiscover(’Zend_Soap_Wsdl_Strategy_ArrayOfTypeComplex');
With those things in place the resulting response XML becomes:
<items enc:itemType="ns1:RespItem" enc:arraySize="2" xsi:type="ns1:ArrayOfRespItem">
Not exactly what we were after, but certainly better than the original solution.
Incidentally, this solution appears to not require the classmap
option to be passed into the Zend_Soap_Server
constructor. I’m guessing that whatever little issue the classmap
option was overcoming, the change in complex type discovery strategy achieves the same thing and then some.