« E-Mail Rate Limiting | Main | Graceful Framework Degradation »

PHP and Soap Headers

When I first began experimenting with PHP-SOAP, the one thing I noticed immediately was the distinct lack of documentation on php.net for SOAP. Functions and features go undocumented (eg __SetSoapHeaders) and those that are found include little relevant information beyond language syntax. The following blog post(s) cover some of the concepts that I found difficult to find any information on.

This post concerns itself with how PHP-SOAP handles SOAP Headers as a client and a server. SOAP Headers provide a standardized mechanism for web services to include function modifiers that do not correspond to directly to the function being called. The most common use of headers are for authentication purposes (eg username/password or token). The authentication data could technically be included as just another function parameter but doing so clutters the function semantics.

The complete code including WSDL, client, and server can be found here. You will need to manually change the soap:address in the WSDL to your own server.

If you look at ed.wsdl, you should be able to tell the following about the service:

- it is Document/Literal
-- the binding is defined with a style of document
-- for each operation in the binding, inputs/outputs have use defined as literal

- it defines a single function named "hello"
--accepts a complex element named "hello" that contains a single attribute "firstname"
--accepts a SOAP Header consisting of a single complex element named "helloHeader" that contains a single attribute "lastname"
--returns a complex element named helloResponse that contains a single attribute "goodbye"

As you can see, the service is fairly light-weight. In PHP, the complex elements will simply become associative arrays or stdClass objects.

The important piece to note is how the SOAP Headers are defined. A <header /> element from the soap namespace must be defined within the binding element for the operation. This informs the client that a header may be sent. The message and part of the header indicate the structure of the header. The message must point to a <message /> element. The part should point to a <part /> within that message.

The reason why the header object must be explicitly defined as a message element as opposed to simply a schema element is because the headers are processed as a separate function call. A SOAP Header should only be used for function modifiers, not arguments. As the header could be defined for multiple functions, it makes sense that the header processing be done without regard to the function being called.

If you look at ed_server.php, you will notice the class Ed{} has two functions defined: hello and helloHeader. When a client includes the header with a call to hello, helloHeader() will be the first call after service(). The value from the header is stored as a private class variable and will be used later in the local hello() call. The result is an object with a single element "goodbye" consisting of the firstname and possibly lastname that were submitted.

Lastly, PHP-SOAP is somewhat immature in terms of SOAP Headers when used as a client. In other toolkits such as .NET and AXIS, headers that are defined as complex elements are automatically (de)serialized to/from the appropriate custom class. In PHP-SOAP, there is only one generic header class that must be explicitly told what definition to use. You do this by specifying the namespace, object name, and values in the SoapHeader constructor. For really complex headers (eg one element is an array of other complex elements), the values simply become multi-dimensional arrays.

Hopefully, this post provides a bit of insight into how you can incorporate headers into your web service with PHP-SOAP. My next post will discuss SOAP faults and how other toolkits interpret your faults.


Ed

TrackBack

TrackBack URL for this entry:
http://www.typepad.com/t/trackback/2354520/17574970

Listed below are links to weblogs that reference PHP and Soap Headers:

Comments

Nice tutorial, Ed. Should be helpful for people getting started with PHP + Soap.

Do you know some trick to add custom attributes to the soap headers?

I do not know of a way to add custom attributes to a soap header in PHP-SOAP. If all else fails, you could try NuSOAP which will allow you to specify a complete header string containing anything you'd like.

Hi guys, looks like it's been a a while since you posted on this tech blog. May I suggest adding code samples to the API section on the Bronto site? Our use case for the API is to pass along information from Bronto to Google Analytics using GA's urchinTracker as the data receiver. Among other things I'd like to generate "fake page views" in GA profiles we would set up for our newsletters to track newsletter opens in GA. The reason I need to go through the API is that most email clients won't execute GA's javascript. Right now we're only tracking newsletter click-throughs in GA.

We're also interested in extracting data that Bronto doesn't present in reports such as contact subscribes/unsubscribes/bounces per day.

Hey Ed.
This is bl00dy fantastic.
Exactly what I was looking for - simple, function and self-explanatory.
It's ridiculous exactly how little good documentation and how much bad/useless documentation about exactly what you've done here.
Cheers,
Chris

Thx for your Tutorial.
As Aamer said:
It was really helpful getting started with PHP and SOAP, especially with using customized SOAP-Headers.

Thx again,

Lars

Thanks for this tutorial, with this simple example.
I've a question : how do you deal with errors, fault, that you could throw thru soap response ? I don't find any reference to that ...

Thanks in advance,
Matthieu

In response to those asking about custom attributes in Soap headers. The only way I've found is to catch the xml on the way out and rewrite the xml using preg_replace or something similar.

You need to create a subclass of SoapClient and override the __doRequest method. Have a look for "Dirty Secrets of SOAP" in google to find an exact explanation.

Hi,

Thanks for the great help, I found it very useful for understanding how to get headers from a soapserver class.

I was wondering if you would know how to also return the same header in the response?

I would like a client to "tag" a request with a unique ID in the header, and I would like the response to the request to contain the identical "tag" in the header back to the client.

Thanks!

Hi,

Thanks for the great help, I found it very useful for understanding how to get headers from a soapserver class.

I was wondering if you would know how to also return the same header in the response?

I would like a client to "tag" a request with a unique ID in the header, and I would like the response to the request to contain the identical "tag" in the header back to the client.

Thanks!

Hi,

Thanks for the great help, I found it very useful for understanding how to get headers from a soapserver class.

I was wondering if you would know how to also return the same header in the response?

I would like a client to "tag" a request with a unique ID in the header, and I would like the response to the request to contain the identical "tag" in the header back to the client.

Thanks!

Hi,

Thanks for the great help, I found it very useful for understanding how to get headers from a soapserver class.

I was wondering if you would know how to also return the same header in the response?

I would like a client to "tag" a request with a unique ID in the header, and I would like the response to the request to contain the identical "tag" in the header back to the client.

Thanks!

I think this is a great tutorial. I will forward this to my friends for study.

very helpful your example

Thank you so much, man.

Hi,


I am venkat. I tried and tired of creating a web service using php and nusoap. I have to call a complex data type and have to pass the login and password details as hardcode value. The result has to return the users details. I dont know how do it.

Please help, it would be a great help for me.

Thanks
Venkat

Post a comment

If you have a TypeKey or TypePad account, please Sign In