PHP中的SOAP UI定义和实现

I intent to implement a webservice using PHP. The creators of the web-service sent me the WSDLs required via email and I was able to import them into Soap UI and test them.

Seeing that they work just fine, I'm tasked with repeating the same process in my PHP application. I did a bit of googling around, to find that PHP5 already supplies a SoapClient to consume webservices. I even tested two examples and they worked just fine. But not the one that was running using Soap UI.

SoapClient receives a URI of the WSDL file as the first parameter1 - is this the url of the service that soapui shows in the top bar? I noticed that the other webservices I tested, if the uri was copied and pasted to a browser, an XML format would be returned with the data regarding the webservice. With the data soapui was pointing as the endpoint, the browser would simply output a "Lenght Required" 411 error message.

So my question is, is the .xml file that SOAP ui uses to import a project the one I should point in my php? Like:

SoapClient ( "file:://C:\users\something\webservice.xml?wsdl",
['service'=>'login', 'username'=>'something', 'password'=>'secret' ] );

I would expose the .xml I received with the webservice information, but I'm afraid of leaking sensitive data. I will copy the header of the request, ommiting any sensitive data

<?xml version="1.0" encoding="UTF-8"?>
<con:soapui-project activeEnvironment="Default" name="" resourceRoot="" soapui-version="5.2.0" abortOnError="false" runType="SEQUENTIAL" id="" xmlns:con="..."><con:settings/><con:interface xsi:type="con:WsdlInterface" wsaVersion="NONE" name="..." type="wsdl" bindingName="{...}GenericTicketConnector_Service" soapVersion="1_1" anonymous="optional" definition="file:/D:/.../Documents/file.wsdl" id="..." xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><con:settings/><con:definitionCache type="TEXT" rootPart="file:\D:\...\Documents\file.wsdl"><con:part><con:url>file:\D:\...\Documents\file.wsdl</con:url><con:content><![CDATA[<--!...-->
<wsdl:definitions name="GenericTicketConnector" targetNamespace="http://www.otrs.org/TicketConnector/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://www.otrs.org/TicketConnector/">
  <wsdl:documentation/>
  <!--Warning: This WSDL file is for Development and Test purposes ONLY!-->
  <wsdl:types>
    <xsd:schema targetNamespace="http://www.otrs.org/TicketConnector/">

After this the .xml file looks like a normal wsdl file, describing the webservices supplied, the format of the request, the respose... etc...

Thank you.

I'm not that familiar with SoapUI, but for the WSDL parameter of the ctor of SoapClient (first parameter) it's not much of a difference if you have it as a HTTP URL or a path to a local file.

Consider the following example which downloads the WSDL file on the fly to the directory where the example script is stored and then uses the local file instead of the URL:

// just an example webservice WSDL
$wsdl = 'http://www.webservicex.net/globalweather.asmx?WSDL';

// store the WSDL file in current directory if it does not yet exist
$filename = __DIR__ . '/globalweather.asmx.wsdl';
if (!is_readable($filename)) {
    file_put_contents($filename, fopen($wsdl, 'r'));
}

$soapclient = new SoapClient($filename);
$params     = ['CountryName' => 'Spain', 'CityName' => 'Alicante'];
$response   = $soapclient->getWeather($params);

var_dump($response);

The response is an (unmapped) stdClass for the GetWeatherResult from the webservice. Already the $soapclient->getWeather call works which only would be the case if the WSDL is successfully loaded.

Note: On the Windows operating system, the question mark ("?") is not valid in a file-name, so take care that you use only valid filenames.

The WSDL file contains all data need to be known to interact with the webservice. So you don't need any more infos.

...
  <wsdl:service name="GlobalWeather">
    <wsdl:port name="GlobalWeatherSoap" binding="tns:GlobalWeatherSoap">
      <soap:address location="http://www.webservicex.net/globalweather.asmx" />
    </wsdl:port>
...

As this example shows, the WSDL contains the concrete URI SoapClient (or SoapUI for that matter) will send HTTP requests to. Try with the local file within SoapUI as well if it accepts it or not.


Edit: The WSDL file of the OTRS Websvervice is available on Github, here is the example adopted to the OTRS webservice, just listing the methods and the types:

$wsdl = 'https://raw.githubusercontent.com/OTRS/otrs/master/development/webservices/GenericTicketConnectorSOAP.wsdl';

// store the WSDL file in current directory if it does not yet exist
$filename = __DIR__ . '/GenericTicketConnectorSOAP.wsdl';
if (!is_readable($filename)) {
    file_put_contents($filename, fopen($wsdl, 'r'));
}

$soapclient = new SoapClient($filename);
print_r($soapclient->__getFunctions());
print_r($soapclient->__getTypes());

Output:

Array
(
    [0] => TicketCreateResponse TicketCreate(TicketCreate $parameters)
    [1] => TicketUpdateResponse TicketUpdate(TicketUpdate $parameters)
    [2] => TicketGetResponse TicketGet(TicketGet $parameters)
    [3] => TicketSearchResponse TicketSearch(TicketSearch $parameters)
    [4] => SessionCreateResponse SessionCreate(SessionCreate $parameters)
)
...