Reputation: 185
I have an issue concerning SOAP calls in PHP. There is a webservice named "DoBulkOperation", that takes a list of whatever, does something, and returns a list with information about what it had done. The important thing here is, that each list element of the request has its counterpart in the response at the same index.
The response I get is something like that:
<Body>
<DoBulkOperationResponse>
<items>
<OperationResponse>
<result>17</result>
</OperationResponse>
<Error>Some error occured</Error>
<OperationResponse>
<result>18</result>
</OperationResponse>
<OperationResponse>
<result>19</result>
</OperationResponse>
<OperationResponse>
<result>20</result>
</OperationResponse>
</items>
</DoBulkOperationResponse>
</Body>
That the correct response to my request. Now, I can say, that there is something wrong with the second list element in the request.
What I get from the PHP SoapClient is not, what I expected:
object(stdClass)#49 (1) {
["items"]=>
object(stdClass)#51 (2) {
["OperationResponse"]=>
array(4) {
[0]=>
object(stdClass)#53 (1) {
["customerID"]=>
int(17)
}
[1]=>
object(stdClass)#52 (1) {
["customerID"]=>
int(18)
}
[2]=>
object(stdClass)#50 (1) {
["customerID"]=>
int(19)
}
[3]=>
object(stdClass)#54 (1) {
["customerID"]=>
int(20)
}
}
["Error"]=>
string(17) "Some error occured"
}
}
The order of the elements is completely broken. Now, it's impossible to decide, which request element leads to which response element.
In WSDL, "items" is defined as sequence.
Is there a way, to force the SoapClient instance to preserve the structure of the response?
Best regards,
Markus
Upvotes: 2
Views: 2082
Reputation: 70893
You have a couple of options here, but for a definitive answer you should present the WSDL for this call.
Set or add array('features' => SOAP_SINGLE_ELEMENT_ARRAYS)
as the option to the SoapClient. It will prevent the result from having arrays only when more than one element is encountered. From what I believe PHP does internalls: On the first element encounter, it is just created, and on the next encounter, the first element is moved into an array and the second then added.
This might already explain the structure you are seeing, and might be able to fix it.
You have to find out the names of the ComplexType structures in the WSDL and can then create PHP classes that are used for these instead of stdClass
. This is very useful for everything, because your IDE can provide you with autocompletion, and you can actually see with which element you are dealing by using get_class()
on it. On the other hand, you cannot create a PHP object that properly acts as the items
structure in your XML, so this might just be cosmetic, but it is necessary for...
__set()
in your custom class to interfere with creating the result.You might be able to create a custom class that is used as the items
which gets set all the properties. Inside the magic function you can try and push the data around. At least you'd be able to debug it with some output.
Set the option trace => true
in the options array, and use SoapClient::__getLastResponse
.
PHP might just be unable to transform the XML structure you get into a proper result. I'd blame the Soap API you are offered. One would usually offer to attach some kind of ID to the request and reuse this ID on the result to enable clients to identify their stuff. At least the structure returned "in the order of the request" should always return the same item and carry the result somewhere internal, like:
<OperationResponse>
<result>17</result>
</OperationResponse>
<OperationResponse>
<Error>Some error occured</Error>
</OperationResponse>
Upvotes: 5