If you intend to use SOAP 0.8 in favor of 0.7.x, please read the following notes carefully, as the changes may either require subtle alterations or make subtle changes in the way SOAP messages are serialized in your application. All of the below is 'TTBOMK'.
1. Background (skip this if you don't care how the library works internally):
PEAR::SOAP's interop is affected by a lot of factors, but one of these is the way types are determined when serialising SOAP messages.
In a PEAR::SOAP client which uses a WSDL file from a server, the WSDL data is used to determine how to serialise SOAP messages, to provide maximum interoperability (as you would expect). If no WSDL data is provided, and you do not use SOAP_Value objects to explicitly specify the types of the values you want to serialise, then a 'best effort' guess will be made - this sometimes works and sometimes doesn't, so it is nearly always better to use SOAP_Value. In a PEAR::SOAP server, the best effort guess is always made when serialising a response to a client, regardless of whether or not you provide __typedef arrays in your server class.
What this means - particularly in cases where you are using SOAP_DISCO_Server to generate WSDL for the client - is that the clients will complain about the SOAP responses from PEAR::SOAP and fail.
2. Changes
- We now serialise data from PEAR::SOAP servers according to the __typedef definitions, if they are present, for improved interop. The __typedef data is converted to WSDL-style data internally for this purpose, so the library behaves as if you had supplied a WSDL file.
- A bug prevented types from WSDL files where the type namespace or any base type namespace contained non-lowercase characters from being correctly serialised; they would be serialised as 'anyType', and with the wrong namespace (for example, SOAP-ENC:arrayType as a base would be serialised incorrectly). This has been fixed.
- User-defined array types that are contained in other user-defined array types (either from WSDL or __typedef) are now serialised differently. If we had an array InnerType containing a number of user-defined structs, and OuterType is an array of InnerTypes, then the new serialisation will be: "InnerType[][x]" instead of "OuterType[]". This improves interop with .NET, and should not break any other platforms (theoretically) since they are semantically identical.
- If no URL is passed to the constructor of SOAP_WSDL, the object will be created but no file will attempt to be parsed. Previously, this would create a SOAP fault. This allows you to use the following two functions: - SOAP_WSDL::parseURL() parses a WSDL file (renamed from parse() in 0.7.x) - SOAP_WSDL::parseObject() parses the __dispatch_map and __typedefs from a PHP object and makes PEAR::SOAP behave the same in future calls to it as if a WSDL file had been supplied (this is mainly for use by SOAP servers via SOAP_Server - see below).
parseObject() can parse a single object or an array of objects. It also accepts a target namespace for the types defined, a WSDL service name for the object or array of objects, and an optional WSDL service documentation string as follows:
parseObject($object | $arrayofobject, $namespace, $service, $docstring)
- SOAP_Server::bind() was renamed to SOAP_Server::bindWSDL().
- SOAP_Server::addObjectWSDL() was added as an interface to SOAP_WSDL::parseObject(), with the same parameters. addObjectWSDL() is the 'parallel' to bindWSDL() in that it associates WSDL-style type data with the SOAP server; whereas bindWSDL() uses a WSDL file, addObjectWSDL() uses the information supplied by an object or array of objects. You only need to use addObjectWSDL() if you don't use addObjectMap() to register objects, since addObjectMap() will now call addObjectWSDL() automatically.
- addObjectMap() has two additional (optional) parameters: a service name and description; these are the WSDL service name and description to associate with the object being registered. The default service name is 'Default', the description is blank.
- In SOAP 0.7.x, a bug where multi-dimensional arrays where one or more dimensions has only a single element would be incorrectly serialised has been fixed.
- A memory leak in the WSDL proxy class code generator has been fixed. Note that proxy methods now return a *reference* to the result, so you should always write:
$result =& $myProxyClass->someWebService();
instead of:
$result = $myProxyClass->someWebService();
- In SOAP 0.7.x, zero-length arrays serialised without reference to a WSDL file or __typedefs would be serialised as "[0]", which is malformed SOAP grammar. They will now be serialised as "xsd:anyType[0]", which is about the best we can do without a specific definition for the array type.
3. Usage notes
Because SOAP_Server::addObjectMap automatically calls addObjectWSDL, you need do nothing to your existing PEAR::SOAP web services for them to take advantage of the type definitions you have provided in __typedefs, but note the following:
- addObjectMap/addObjectWSDL should be able to be called multiple times in a single instance of SOAP_Server to register more type definitions etc. but this needs testing (and may not work at all currently). Passing an array of objects to addObjectWSDL should definitely add that group of objects correctly, together, but for BC reasons, addObjectMap will not accept an array of objects as an argument.
- All methods from all objects are currently limited to one SOAP HTTP binding, and that binding will be associated with a single service.
- If you subsequently call addObjectMap/addObjectWSDL/parseObject with a different service name, the service name of the SOAP_WSDL object (and all the methods registered with it) will be changed.
- Only the 'type' attribute method of declaring types in WSDL is implemented, not the 'element' attribute method.
- You can not currently add a single method at a time to the WSDL data.
- Adding types to the WSDL data will *ONLY* work if you supply both a __dispatch_map and the appropriate __typedefs. If one or other is missing, the standard 'best guess' method of serialising will be used. This is a limitation that can be removed later; it has been done like this for the time being so that we can fix the other bits responsible for this limitation as we go, without breaking backwards compatibility.
- If you use bindWSDL() *and* addObjectWSDL() on the same SOAP_WSDL object, and the object you are registering has its own __dispatch_map and __typedefs, then you are likely to get unpredictable results. Although this should be relaxed in future, right now you should try to avoid mixing the use of WSDL files and __typedefs etc. to provide information for a single set of methods. You may still register an object with addObjectMap() then call bindWSDL() to associate it with a WSDL file if the object does not provide *both* __dispatch_map and __typedef, in which case, the contents of the WSDL file will take priority.
- We have left in wrappers for: SOAP_WSDL::parseURL() - was parse() SOAP_Server::bindWSDL() - was bind()
but these are deprecated and will most likely be removed in time for 1.0, so be sure to change your code to use the new method names!
At 11:37 17/08/2003, Arnaud Limbourg wrote:
Overall, Interop tests should be much better. Chris will provide a link to up-to-date test results.
Most developers will probably find that there isn't a dramatic improvement in interop at this stage, but these fixes are the visible surface of a fair bit of new code that will hopefully come into play more fully in subsequent releases.
Current interop scores can be found at: http://kfc.shacknet.nu/soap_interop/interop_client_results.php
Please test and report to the list for bugs you find in RC1.
Hope I didn't forget anything... phew!
Have fun,
Chris.
-- PHP Soap Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php