SOAP structures in PHP

Handling SOAP structures in PHP can sometimes be really annoying. If an interface is defined in the WSDL as returning an array I can’t be sure that I will get an array. If there is only one element in the array PHP tries to be clever and turn the wanted array into an object which, too me, isn’t really smart. I don’t know if this is a problem/limitation on the client side, server side or if it is just me doing something stupid in the wsdl.

As an example I have the below complex types, message and operation defined in the WSDL file. (The example is not complete of course.)

    <complexType name="KeyValueData">
      <sequence>
        <element minOccurs="1" maxOccurs="1" name="id" type="string"/>
        <element minOccurs="1" maxOccurs="1" name="name" type="string"/>
        <element minOccurs="1" maxOccurs="1" name="data" type="string"/>
      </sequence>
    </complexType>

    <complexType name="ArrayOfKeyValueData">
      <sequence>
        <element minOccurs="0" maxOccurs="unbounded"
                 name="keyval" type="tns:KeyValueData"/>
      </sequence>
    </complexType>
      ...
    <message name="StatisticsListOutput">
      <part name="data" element="tns:ArrayOfKeyValueData"/>
    </message>
      ...
    <operation name="getStatistics">
      <input message="tns:StatisticsListInput"/>
      <output message="tns:StatisticsListOutput"/>
    </operation>

Sending this from the client is an absolute no brainer. It is a simple array containg associative arrays in every slot. When receiving this structure on the client side the original array (the member variable Map in the example) with one element turns into

Class Object
(
    [Map] => stdClass Object
        (
            [item] => Array
                (
                    [0] => stdClass Object
                        (
                            [key] => id
                            [value] => value
                        )

                    [1] => stdClass Object
                        (
                            [key] => name
                            [value] => value
                        )

where an array with multiple elements turn into

stdClass Object
(
    [Map] => Array
        (
            [0] => stdClass Object
                (
                    [item] => Array
                        (
                            [0] => stdClass Object
                                (
                                    [key] => id
                                    [value] => value
                                )

                            [1] => stdClass Object
                                (
                                    [key] => name
                                    [value] => value
                                )

This is annoying. Just imagine the situation when you have multiple arrays in arrays… Which actually does happen every once in a while when sending compounds of various elements declared as ComplexTypes in the WSDL.

Is it a feature, quirk or anti social behaviour? I don’t know. If there is another way I’d like to hear about it.

Tagged with: , , ,
Posted in PHP
20 comments on “SOAP structures in PHP
  1. gaetano says:

    Quite annoying indeed.

    But the fault lies in xml being a child of sgml: it was not designed for storing data, but rather for storing documents.
    Just think at how much money has globally been lost in the world in time spent thinking whether some piece of data was to be coded as an element attribute or a sub-element…
    And xsd is the most unnecessarily bloated and complex xml definition language that could be bolted on top of it. Quite an unlucky combination for the SOAP guys.

    If you want to keep mental sanity and decent execution speed, go for json or xmlrpc.

  2. It’s considered a feature. Create your soap client object like this:

    $soap = new SoapClient(
        $wsdlurl,
        array('features' => SOAP_SINGLE_ELEMENT_ARRAYS));
    

    See also the comment in: http://no2.php.net/manual/en/function.soap-soapclient-construct.php

  3. DrydenMaker says:

    gaetano

    That would be nice to force third party data providers to use JSON, but reality is that there are a bunch of lovely folks out there who think SOAP should work as advertised.

    I have to agree with Danne. We deal with a couple shops that love their complex data types. They hand coded their WSDLs taking full advantage of them. When we come across these sorts of things, PHP falls flat on it’s face.

    If I could motivate anyone in the internals, I would say: who cares about PHP6, give me a fully WSDL compatible SOAP extension and a comprehensive solution for complex data types.

    There are a couple PHP coded projects out there that try to make up for the shortcomings, but those things should be native and predictable. I think it is ironic that PHP’s weakest point right now is SOAP.

  4. It’s considered a feature. But there’s a way to make it work better. There’s an option when creating the SOAP object called SOAP_SINGLE_ELEMENT_ARRAYS. You can google or search the PHP documentation for it.

  5. Nick says:

    Not sure if this will come thru in the comment, but here is a slightly different WSDL construction that I am fairly sure will facilitate always returning an array, even if the data structure encoded in it has 1 element.

    
      
        
          
        
      
    
    

    The corresponding PHP server code to create the response would be something like

    new SoapVar($arrayOfKeyValueData, SOAP_ENC_ARRAY, "ArrayOfKeyValueData", "[your target namespace]");

  6. Nick says:

    Uh… strike 1. try again…

  7. Nick says:

    strike 2… almost done. last try…

    <complexType name="ArrayOfKeyValueData">
    <complexContent>
    <restriction base="SOAP-ENC:Array">
    <attribute ref="SOAP-ENC:arrayType"
    wsdl:arrayType="tns:KeyValueData[]" />
    </restriction>
    </complexContent>
    </complexType&grt;

  8. David Zülke says:

    http://bugs.php.net/bug.php?id=36226 says:
    $x = new SoapClient($wsdl, array('features' =>
    SOAP_SINGLE_ELEMENT_ARRAYS));

  9. Lukas says:

    Havr you tried the following:


    $x = new SoapClient($wsdl, array('features' =>
    SOAP_SINGLE_ELEMENT_ARRAYS));

    Not sure if this is documented in the manual though.

  10. Kevin Nuut says:

    What about the issue of if you are building your WSDLs this way, using WS-I compliant arrays, you can’t properly pass or retrieve arrays without everything wrapping in stdClass objects?

    However, if he built the exact same WSDL using soap-enc:Array, this all would have returned the results in a nice package of:

    array(
    array(
    ‘id’ => xxx, ‘name’ => yyy, ‘data’ => zzz),
    array(
    ‘id’ => aaa, ‘name’ => bbb, ‘data’ => ccc));

    I have yet to find a solution for this WS-I soapenc:Array issue.

  11. Erwan Martin says:

    This is how I declare arrays in my wsdls.

  12. Chaitanya says:

    SOAP CONCEPTS THOROUGH

  13. Chaitanya says:

    I want to retrieve wsdl values from soap.

  14. Karl says:

    Thanks for posting this. The SOAP_SINGLE_ELEMENT_ARRAYS fix is just what I wanted. Crazy that it doesn’t behave this way from the start, but it’s so php to try to anticipate what I might want, when what I really want is for the API to respond with the same structure whether the array has 1 or more elements.

  15. derjanni says:

    Hi … I did a tutorial covering Complex Types as well with NuSOAP in PHP: http://www.kammerath.net/php-und-soap.html

    Maybe that helps others looking for a solution to it.

    Best regards,

    Jan

  16. Yoni says:

    Hello,

    Did you a find a solution to match your PHP code to the first Class object definition ?

    I would be glad to see how you did that.

    Thanks

  17. Jeane Watte says:

    Have you ever considered writing an ebook or guest authoring on other websites? I have a blog based on the same ideas you discuss and would love to have you share some stories/information. I know my viewers would appreciate your work. If you are even remotely interested, feel free to send me an email.

  18. Adriana says:

    It’s hard to find your articles in google. I found it on 17 spot, you should build quality backlinks
    , it will help you to increase traffic. I know how to help you, just
    type in google – k2 seo tips and tricks

  19. Who would have top eleven hack seen. Grimshaw
    revealed top eleven hack the threat of the 2013 final.
    Early strongmen would often perform triples; typically a Two-Hands anyway, a player in the
    World Cup. Given that Performance Sports Group, the defensive line of
    a back three, I look at that point on as a Trojan football player.
    These people will remember George Weah for the ball frequently.
    I don’t know if he’s about that life.

    my web page – top eleven hack best

  20. Great post. I was checking continuously this blog and I am impressed!

    Extremely helpful info particularly the last part :) I care for such
    information much. I was seeking this particular information for a long time.

    Thank you and best of luck.

    My web-site … wordpress websites

4 Pings/Trackbacks for "SOAP structures in PHP"
  1. [...] Lundqvist is frustrated with the SOAP functionality that comes native with PHP on one very specific subject – its handling of SOAP [...]

  2. [...] Lundqvist is frustrated with the SOAP functionality that comes native with PHP on one very specific subject – its handling of SOAP [...]

  3. [...] check the SOAP Structures in PHP Article. It has a great point of view of how SOAP Strucutres work on PHP and what to do if you want the [...]

  4. [...] Format, je nachdem ob die Response nur einen oder mehrere Datensätze enthält, ist nur (PHPs Schuld (via dotvoid.com). Allerdings: It’s not a bug but a [...]

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>