I'm not sure if this is php bug (bad implementation) or my bug (bad understanding of the SOAP protocol / SoapServer as this is the first time I'm using SoapServer)
I've noticed that if there are two or more operations with the same wsdl:part
(even if the wsdl:message
, operation and soapAction are different), The SoapServer
will allways call the first function. In this example, I've two functions multiply2
and multiply4
both having num
(int) as input parameter. earlier today, If I change the part name (service1.wsdl) the functions are mapped correctly.
Although, I don't mind using different names it looks to me like a bug. Am I missing something or should I open a bug ?
This is simple example I've crated:
Very simple php class
<?php
class Multi
{
function multiply2($num) { return ($num * 2 ); }
function multiply4($num){ return ($num * 4 ); }
}
?>
And slightly changed SoapServer (with added logging - adapted from this post) but the issue appears when I'm using the plain SoapServer as well:
$server = new overloadedSoapServer("service.wsdl", array('soap_version' => SOAP_1_2,'encoding' => SOAP_ENCODED));
$server->setClass("multi");
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$server->handle();
}
This is the client code:
ini_set("soap.wsdl_cache_enabled", "0");
$client = new SoapClient('service.wsdl');
$client1 = new SoapClient('service1.wsdl');
echo "<pre>\nFrom service.wsdl:";
echo "\n".$client->multiply2(10);
echo "\n".$client->multiply4(10);
echo "</pre>";
echo "<pre>\nFrom service1.wsdl:";
echo "\n".$client1->multiply2(10);
echo "\n".$client1->multiply4(10);
echo "</pre>";
service.wsdl
and service1.wsdl
are basically the same file, with two exception:
- their endpoint are different (
service.wsdl
points tohttp://tests.simsimy.info/web/service.php
andservice1.php
tohttp://tests.simsimy.info/web/service1.php
each endpoint uses the appropriate wsdl to load theSoapServer
) - in
service.wsdl
multiply2Request
andmultiply4Request
have the as part name -num
, while inservice1.wsdl
the names are different (num2
andnum4
)
This is the full wsdl of service.wsdl
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://tests.simsimy.info/web/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="service"
targetNamespace="http://tests.simsimy.info/web/">
<wsdl:message name="multiply2Request">
<wsdl:part name="num" type="xsd:int"></wsdl:part>
</wsdl:message>
<wsdl:message name="multiply2Response">
<wsdl:part name="res" type="xsd:int"></wsdl:part>
</wsdl:message>
<wsdl:message name="multiply4Request">
<wsdl:part name="num" type="xsd:int"></wsdl:part>
</wsdl:message>
<wsdl:message name="multiply4Response">
<wsdl:part name="res" type="xsd:int"></wsdl:part>
</wsdl:message>
<wsdl:portType name="dd">
<wsdl:operation name="multiply2">
<wsdl:input message="tns:multiply2Request"></wsdl:input>
<wsdl:output message="tns:multiply2Response"></wsdl:output>
</wsdl:operation>
<wsdl:operation name="multiply4">
<wsdl:input message="tns:multiply4Request"></wsdl:input>
<wsdl:output message="tns:multiply4Response"></wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="serviceSOAP" type="tns:dd">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="multiply2">
<soap:operation soapAction="http://tests.simsimy.info/web/multiply2" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="multiply4">
<soap:operation soapAction="http://tests.simsimy.info/web/multiply4" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="multiply_service">
<wsdl:port binding="tns:serviceSOAP" name="serviceSOAP">
<soap:address location="http://tests.simsimy.info/web/service.php" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
The changed part in service1.wsdl
:
<wsdl:message name="multiply2Request">
<wsdl:part name="num2" type="xsd:int"></wsdl:part>
</wsdl:message>
<wsdl:message name="multiply2Response">
<wsdl:part name="res" type="xsd:int"></wsdl:part>
</wsdl:message>
<wsdl:message name="multiply4Request">
<wsdl:part name="num4" type="xsd:int"></wsdl:part>
</wsdl:message>
<wsdl:message name="multiply4Response">
<wsdl:part name="res" type="xsd:int"></wsdl:part>
</wsdl:message>
When I run the client code I get the following ouput:
From service.wsdl:
20
20
From service1.wsdl:
20
40
You can change the binding style in your wsdl from 'document' to 'rpc'.
First I thought it is a cache problem as your posted server code above does not contains the ini_set() to disabled the cache. But is isn't a cache problem.
Having traced http traffic. Client seems working porperly it is a SoapServer problem. (Like you mentioned).. Further investigating ...
A bug report has already been filed - although it is currently unclear if it is a bug.
Workarounds are mentioned in the bug report too. You can change the binding style to rpc if this is ok for you:
Change
<soap:binding style="document"
to
<soap:binding style="rpc"
This workaround works for me. You will find a very interesting article on how binding styles work here. This may help you to decide whether rpc binding style is ok for you or not.
来源:https://stackoverflow.com/questions/13957539/soapserver-maps-functions-incorectly-when-the-wsdl-messages-have-the-same-part-n