Structs, Arrays, and Arrays of Structs in WSDL
I’ve been getting into creating web services lately for all sorts of tasks. I started out with XML-RPC and was hammering away pretty well with it until I discovered that .Net didn’t like to play with XML-RPC. Since this was for a top-priority project at work, I dove head first into SOAP despite not wanting to have to deal with WSDLs. It seemed that I was in luck. Built-in SOAP support for PHP 5.x seemed to have finally matured and I didn’t have to rely on sparsely-documented libraries. Once I got the hang of writing a WSDL (basically, I found a good template), I was well on my way. The great thing about SOAP and WSDLs are that the server and client both automatically seem to handle a lot of error-checking for you. For a high priority action item with just a couple of hours to complete it and diving into something I knew little about, this worked out very well.
I chugged along at my various projects and web services until I hit a roadblock. I wanted to return a multi-dimensional array from PHP. That’s when it all came to a screeching halt. I could not find ANY documentation on this no matter how many different ways I tried to search using Google. Heck, I even tried Bing! No luck at all. So, I decided to put it off for a few days just to give myself time to get over the frustration. Every time I started to try to think about it, I would feel the onset of a headache and just get irritable with myself. Headaches and irritations are terrible for programming!
After a few days, I decided that maybe what I needed was to learn a little bit about the basics of SOAP. Web sites seemed to just assume you knew what you were doing with SOAP and WSDLs from the get-go. I had a working web service with SOAP and a WSDL, but I didn’t have a clue what was going on (and, honestly, I still don’t have a concrete grasp on it all). However, it turns out that sometime several months ago, the company I work for bought an O’Reilly book on SOAP and it was collecting dust on my boss’s bookshelf. I immediately snagged it and started reading. A bunch of it was pretty basic but helped clarify some things. Then, there was about a page that roughly covered structs and arrays. It wasn’t much, but it was just enough. A struct is basically an associative array value (name = ‘Garrett’, age = 27). And an array is just a bunch of repeating values. So, what if I declared a struct complex type and then an array complex type that used the struct as the value. I tested returning arrays and structs individually and they both worked. Then I put them together…and they still worked! In essence, I have finally figured it out.
So, for your geeky pleasure, I have decided to document this experience and hope that Google indexes it for anyone else out there using PHP and SOAP to return the elusive multi-dimensional array. I won’t include the whole WSDL, but just the main message and types portions and the PHP functions used to return them.
(I apologize for the horizontal scrolling, but I like to keep my code tabbed and formatted nicely.)
<!-- The types declarations --> <types> <schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.xmltc.com/railco/transform/schema/" > <!-- Here's the struct for name and age --> <complexType name="TestStruct"> <sequence> <element name="name" type="xsd:string" /> <element name="age" type="xsd:string" /> </sequence> </complexType> <!-- Here's an array that just returns a series of simple string repeating values --> <complexType name="ArrayOfString"> <complexContent> <restriction base="SOAP-ENC:Array"> <sequence> <element name="test" type="string" minOccurs="0" maxOccurs="unbounded" nillable="true" /> </sequence> <attributeGroup ref="SOAP-ENC:arrayType" xsd:arrayType="string[]" /> </restriction> </complexContent> </complexType> <!-- Combine the two and we return an array of repeating structs! --> <complexType name="ArrayOfStruct"> <complexContent> <restriction base="SOAP-ENC:Array"> <sequence> <element name="test2" type="TestStruct" minOccurs="0" maxOccurs="unbounded" nillable="true" /> </sequence> <attributeGroup ref="SOAP-ENC:arrayType" xsd:arrayType="TestStruct[]" /> </restriction> </complexContent> </complexType> </schema> </types> <!-- And returning the ArrayOfStruct in a method --> <message name="test_struct" /> <message name="test_struct_resp"> <part name="test" type="xsd:ArrayOfStruct" /> </message>
Now, for the PHP.
# Return the array function test_array() { return array('hi','there'); } # Return the struct function test_struct() { $arr = array( array( 'name' => 'Garrett', 'age' => 27 ), array( 'name' => 'Amy', 'age' => 28 ) ); return $arr; }
I didn’t include the code for returning the struct with a single entry, but I think you get the picture. Here’s what the response looks like in SOAP Client for the Mac (click image for larger version).

I really hope that helps someone out there because it frustrated me to no end for several days!
Also, if you do have a Mac, I HIGHLY recommend downloading SOAP Client. It is a very excellent piece of software that does one thing and does it very, very well!
Tags: array, complex type, multidimensional array, php, soap, struct, wsdl