About the Author

author photo

Adam Trachtenberg is the Director of the LinkedIn Developer Network, where he oversees developer relations and marketing for the LinkedIn Platform. Before LinkedIn, Adam worked at eBay in platform product management and marketing. Even earlier, he co-founded Student.Com and TVGrid.com. Adam is the author of PHP Cookbook and Upgrading to PHP 5. He lives in San Francisco.

See All Posts by This Author

PHP SOAP vs. SDO

In my role as eBay Platform Evangelist, I spend a lot of time exploring different XML technologies.

SOAP is obviously the big one. I use the PHP 5 ext/soap extension, which is great, but there’s actually another PHP SOAP extension that might be even better. No, it’s not PEAR::SOAP or NuSOAP; it’s axis2.

If you haven’t heard of axis2, you’re not alone. That’s because it’s a pecl extension that’s still in beta, so there aren’t a lot of people using it yet. However, it’s a PHP version of the Apache Axis 2.0 SOAP stack.

Unlike ext/soap, which is recreating SOAP one feature at a time, Axis 2.0 already supports a good portion of the WS-* specifications. So all that needs to happen is for someone to write the hooks between PHP and Axis 2.0, which is far easier than actually writing the features themselves.

I met a number of people from WSO2, the company that’s writing Axis 2.0, and they’re quite excited about the extension. However, they did mention it’s still in beta, so I haven’t actually spent any time using it yet.

The other PHP XML extension I’ve been hearing a lot about is SDO. SDO is an attempt to provide a standard data interface regardless of the backend datasource. So, for example, you can interact with XML data in the exact same manner as information pulled from your database.

At OSCON and ApacheCon, I’ve run into a couple of people from IBM who have been doing the heavy lifting on this extension, and we’ve had a number of interesting chats with them about eBay Web services and SDO, but I hadn’t had any free time at work to install the extension.

Therefore, when I had a little free time today between the end of my session and lunch, I sat down and reproduced a short code example that I had wrote using ext/soap with SDO instead.

Here’s the key portion of the original code:

// Print Titles and Mileage
if (isset($response->SearchResultItemArray)) {
    foreach($response->SearchResultItemArray as $item) {
        printf("%s\n\t%d miles\n", $item, $item->ItemSpecific['Mileage']);
    }
}

This iterates through a search result for eBay Motors listings and prints out the title and the mileage for each individual item.

Normally the code would be far more complex, but through a series of ext/soap class mappings I wrote that implement the IteratorAggregate and ArrayAccess interfaces, along with the __toString() magic method, I’ve managed to abstract away a number of the complexities.

Best I can tell, SDO doesn’t give me quite the same level of control, but it does implement a number of these features for me out-of-the-box.

Here’s my rewrite using SDO:

foreach ($root->SearchResultItemArray->SearchResultItem as $item) {
    $title = $item->Item->Title;
    $mileage = $item->ItemSpecific["NameValueList[Name='Mileage']"]->Value[0];
    printf("%s\n\t%d miles\n", $title, $mileage);
}

It’s not quite as brief, but I do get this nice XPath-like filtering that lets me pull out the the value of the car’s Mileage in one line. Pretty handy.

I had to implement the ArrayAccess interface to get this to work under ext/soap, which included this method:

public function offsetGet($name) {
	if (! is_array($this->NameValueList)) {
		$this->NameValueList = array($this->NameValueList);
	}

	foreach ($this->NameValueList as $NameValueList) {
		if ($NameValueList->Name == $name) {
			return $NameValueList->Value;
		}
	}

	return null;
}

Not the hardest thing in the world to write, but this is just one of the custom class maps that will arise in our data schema, and SDO takes care of them all automatically.

Still, right now I think I prefer my ability the greater control I have over the interface with ext/soap. Our SOAP schema isn’t that pretty since there are lots of list, array, and hash wrappers. Through classmaps and interfaces I can turn these into native-looking PHP arrays and hashes.

I may be introducing a leaky abstraction, but I think this is better than exposing a NameValueListArrayType for people to wrangle with.

Like ext/soap, SDO requires you to define your data using an XML Schema. While we actually publish a stand alone XML Schema file, SDO will also happily parse a WSDL file, too, which is nice.

However, it will not directly consume a SOAP message because the WSDL doesn’t include any mention of the SOAP envelope wrapper. I needed to rip out the contents of the SOAP body into a separate XML document in order to get SDO to parse my data. Oddly, this corresponds perfectly with our “XML API,” so I could use that to retrieve properly formatted data that I can pass directly to SDO.

Where SDO really falls down for me is performance. Admittedly, eBay is a pathological case, but our WSDL file is 2.94 Megs in size. When I feed that to SDO, it takes 8.5 seconds to process the XML Schema data. Yikes!

I don’t mind a one-time start up hit, but it doesn’t appear that SDO can cache a parsed version of the schema. In contrast, ext/soap has both an on-disk and in-memory WSDL cache.

This means it takes SDO about 8.7 seconds to process the schema, load in data, and print out the information — and all with locally stored files.

In contrast, ext/soap takes as little as 0.55 seconds to pull in a cached version of the WSDL from the disk, go out over the network to query eBay via SOAP, wait for eBay’s SOAP server to run a database query on its end and send back a SOAP response, parse the SOAP envelope, and print out the exact same data. If I was using the in-memory cache, I think it’d be even faster, and I’m sure the big bottleneck here is talking to eBay.

Now, I’ve spent all of 60 minutes playing with SDO, so it’s quite possible that I’m missing some obvious configuration flag. If not, I hope IBM can do something to help speed up the performance, since while I could probably write a script to break apart our schema to create individual files that contain all the possible types on a per-call basis, I am hoping I don’t need to.

In the meantime, I’m going to continue exploring SDO to see what else I can do with it because I’ve sure I’ve only grazed its surface.

[Update: I cannot get the axis2 extension to compile, despite trying a number of different versions of Axis2c and both Linux and Mac OS X. I may try again tomorrow.]

Popularity: 38% [?]

There Are 3 Responses So Far. »

  1. Hi Adam,

    I’m really glad you found the time to take a look at SDO and give it a try with the eBay API. Your feedback is very helpful and gives us a few areas to focus on. Some specific comments below:

    >> However, it will not directly consume a SOAP message because
    >> the WSDL doesn’t include any mention of the SOAP envelope wrapper.

    In PHP 5.2 ext/soap has been extended to support a typemap capability. This can be used to register serialization/deserialization functions for each complex type on the Web service interface. We use this in our Service Component Architecture (see http://osoa.org/display/PHP/SCA+with+PHP) implementation to enable SDOs to be used for complex types on Web service calls. The typemap functions get called by ext/soap to convert between the xml for a complex type and an object (in our case an SDO).

    The big downside to this approach is that currently the WSDL will be loaded twice! – once by ext/soap and once by SDO. This doesn’t bode well for large WSDLs, based on your later comments around performance.

    >> Oddly, this corresponds perfectly with our “XML API,” so I could use
    >> that to retrieve properly formatted data that I can pass directly to
    >> SDO.

    This sounds like something we’d like to give a try :-)

    >> When I feed that to SDO, it takes 8.5 seconds to process the XML
    >> Schema data. Yikes!

    Yikes indeed! Thanks for pointing this out. Performance is not something we’ve had any feedback on previously, so the eBay scenario will help us a lot here.

    Cheers, Graham.

  2. Hello Graham –

    I’m glad my post was useful — I am still exploring everything you can do with SDO, so I am really just stumbling around for now.

    I’m familiar with ext/soap’s classmapping feature — I’m using it now with the eBay API to create my interface. Can you provide me with a simple PHP 5 code example of how I might be able to hook into this using SDO as part of a Web services client?

    I won’t worry for now about double WSDL parsing and performance. That’s something that I’m sure can be worked out, particularly given that ext/soap can store a parsed WSDL file in memory if speed is critical. (That patch came from Yahoo!, so I am sure it is “fast enough” for most people.) I bet SDO could leverage that (or steal some ideas from it) if things came down to it.

    Besides, our WSDL is so large that it’s often a good test for regressions and performance. I know a number of other Web services tools companies and applications have found it useful. I think Borland includes it as part of their unit testing for Delphi.

    -adam

  3. SDO is still a baby. Performance is sure to improve over the next year or so, giving you just enough time to fix your WSDL ;-) When all is said and done, SDO is a lot more than a PEAR extension… you’re comparing an apple to a fruit stand. Such an awesome abstraction between the class interface and the message protocol is exactly the kind of technology that is propelling the web forward as a distributed computing (read: “value”) platform.

    By the way, thanks for a great presentation at Zend Conference 2006.

Post a Response