TL;DR; Use SoapParam.
Yes, I know, SOAP is dead. But I have to use it in a client project where a Laravel application needs to call another service (Smilehouse Workspace, ugh!), which only provides a SOAP API.
I didn’t have WSDL available 1), so I passed null as the “wsdl” parameter to SoapClient constructor:
$client = new \SoapClient(null, [ 'location' => 'https://myworkspace.url/workspace.admin/openinterfaceaddress', 'uri' => 'http://www.smilehouse.com/wsdl', 'trace' => true, ]);
‘trace’ => true is useful when you want to see the XML sent in the request.
The other end expects the call to have a parameter called “String_1”. SoapClient::__soapCall documentation for the arguments parameter says:
An array of the arguments to pass to the function. This can be either an ordered or an associative array. Note that most SOAP servers require parameter names to be provided, in which case this must be an associative array.
So I tried passing an associative array:
return $client->__soapCall('getOpenInterfaceAddress', [ 'String_1' => 'my parameter value' ]);
Maybe I’m missing something, but no matter what I tried, the request XML had “param0” as the parameter name (you can get the request XML with SoapClient::__getLastRequest() when having ‘trace’ => true as SoapClient constructor option):
<SOAP-ENV:Body> <ns1:getOpenInterfaceAddress> <param0 xsi:type="xsd:string">my parameter value</param0> </ns1:getOpenInterfaceAddress> </SOAP-ENV:Body>
Some commenters in the documentation tell to pass parameters as an array of arrays, but that didn’t work either.
Finally I found the solution: I need to use SoapParam object as a parameter:
$result = $client->__soapCall('getOpenInterfaceAddress', [ new \SoapParam('my parameter value', 'String_1') ]);
Now the other end accepted my request and I could move on to bang my head against the next wall!
- Later I found out there is WSDL for this openinterfaceaddress API too. So I could just use the WSDL mode instead. Bah.