Your use of str_replace with XSD_XMLANY may fix the problem I had heard of previously.
On 18 Apr 2007, at 16:45, Scott Nichol wrote:
We're building the request using the DomDocument object and then,
usually using a combination of SoapVar and one of it's constant
(second) arguments .. usually XSD_ANYXML - we're struggling so much
with pure trial and error!
This is a method that will typically get you tantalizingly close to
the right SOAP payload, but almost never totally correct.
It's a shame, that DOMDocument isn't 100% correct - it's a brilliant
method for mocking up what essentially is an XML document! I've
managed to use it correctly to hook into an insurance companies site,
with code like this:
$___name_removed___->getSoapWorker()->PerformQuote(new SoapVar
(str_replace('<?xml version="1.0" encoding="UTF-8">', '', $dom-
>saveXML()), XSD_ANYXML));
Where the $___name_removed___ is a generic class, and getSoapWorker()
returns an instance of PHP's built in SoapClient - the str_replace is
to strip the XML declaration from the resulting output of $dom, which
is - as you may imagine an instance of PHP's DOMDocument.
PerformQuote() is a method from the WSDL - which when examined
reveals that it expects the following:
(sorry to attach an image, it saved on typing!)
Using the DOMDocument to spec out an XML file, where the root node is
called 'PerformQuoteRequest' (the same you will note, as the WDSL
generated method) the above method seems to work, although - I'm
currently facing server-side XSD errors, but I know that's because
one of my node trees is malformed.
How did you learn to use SOAP with PHP correctly, and how would you
advise we learn the same ?
Because I came to NuSOAP with lots of SOAP experience, my learning
curve was mainly mapping my knowledge to NuSOAP's design. It
sounds like you are probably learning SOAP and a PHP implementation
at the same time, which is much harder. Some tutorials would
probably help you a lot. The ones I did for NuSOAP are,
unfortunately, old enough that I am not sure they work any more.
That says good things about how much NuSOAP has evolved, but does
not help you much.
I did look at the nuSoap tutorials on your site, they - like a lot of
the information online didn't seem advanced enough for the kind of
complex services we were accessing! Having said that though, we just
purchased a copy of "Pro PHP XML and Web Services" - and that doesn't
go much further!
The primary problem arises knowing what 'type' to send a request as -
using __getTypes() on the client is reporting a variety of complex
types (we're working on clients for ~6 web services) - conventional
wisdom says that SOAP is just XML, and XML is just text.. so we can
send a string - bt we're not getting very far with that approach!
There are a couple of ways to attack this, assuming the services
supply WSDL. One is to get a tool like wsdl2php (http://
www.urdalen.no/wsdl2php/). I have not used it, but it has been
mentioned on this list. I believe it will create a PHP proxy for
you to use that (hopefully) will make types easier. A second way
to go is to learn to read the WSDL well enough (it won't take long)
to determine the right complexTypes to use. In NuSOAP, you then
just create an associative array with keys corresponding to the
type elements. An example complexType would be
We just tried briefly with wsdl2php - thanks for the heads up on that
- it generates a class that extends SoapClient, and is good enough to
generate some generic classes with properties that mirror those
expected by the web service; it makes sure you use the correct types
by enforcing the types of your arguments:
public function somewdslgeneratedmethod(CustomTypeClass $parameter)
{
// etc
// ... this code here calls the wsdl method, using the $parameter
you have sent, and of course it knows it is of the correct type to
serialize.
}
<xsd:complexType name="SOAPStruct">
<xsd:all>
<xsd:element name="varString" type="xsd:string" minOccurs="1"
maxOccurs="1"/>
<xsd:element name="varInt" type="xsd:int" minOccurs="1"
maxOccurs="1"/>
<xsd:element name="varFloat" type="xsd:float" minOccurs="1"
maxOccurs="1"/>
</xsd:all>
</xsd:complexType>
Your PHP to create a variable of this type would be
$struct = array('varString' => 'who', 'varInt' => 2, 'varFloat' =>
3.14159);
That seems pretty straightforward to me.
Scott Nichol
Cheers - the rest of our week doesn't seem too bleak now!
Lee Hambley