The SoapClient class
The SoapClient class provides a client for » SOAP 1.1, » SOAP 1.2 servers. It can be used in WSDL or non-WSDL mode.
Class synopsis
public __doRequest (
string $request ,
string $location ,
string $action ,
int $version ,
bool $oneWay = false
): ? string
public __soapCall (
string $name ,
array $args ,
? array $options = null ,
SoapHeader | array | null $inputHeaders = null ,
array &$outputHeaders = null
): mixed
Properties
Table of Contents
- SoapClient::__call — Calls a SOAP function (deprecated)
- SoapClient::__construct — SoapClient constructor
- SoapClient::__doRequest — Performs a SOAP request
- SoapClient::__getCookies — Get list of cookies
- SoapClient::__getFunctions — Returns list of available SOAP functions
- SoapClient::__getLastRequest — Returns last SOAP request
- SoapClient::__getLastRequestHeaders — Returns the SOAP headers from the last request
- SoapClient::__getLastResponse — Returns last SOAP response
- SoapClient::__getLastResponseHeaders — Returns the SOAP headers from the last response
- SoapClient::__getTypes — Returns a list of SOAP types
- SoapClient::__setCookie — Defines a cookie for SOAP requests
- SoapClient::__setLocation — Sets the location of the Web service to use
- SoapClient::__setSoapHeaders — Sets SOAP headers for subsequent calls
- SoapClient::__soapCall — Calls a SOAP function
User Contributed Notes 20 notes
When you need to connect to services requiring to send extra header use this method.
Here how we can to it with PHP and SoapClient
class exampleChannelAdvisorAuth
<
public $DeveloperKey ;
public $Password ;
public function __construct ( $key , $pass )
<
$this -> DeveloperKey = $key ;
$this -> Password = $pass ;
>
>
$devKey = «» ;
$password = «» ;
$accountId = «» ;
// Create the SoapClient instance
$url = «» ;
$client = new SoapClient ( $url , array( «trace» => 1 , «exception» => 0 ));
// Create the header
$auth = new ChannelAdvisorAuth ( $devKey , $password );
$header = new SoapHeader ( «http://www.example.com/webservices/» , «APICredentials» , $auth , false );
// Call wsdl function
$result = $client -> __soapCall ( «DeleteMarketplaceAd» , array(
«DeleteMarketplaceAd» => array(
«accountID» => $accountId ,
«marketplaceAdID» => «9938745» // The ads ID
)
), NULL , $header );
// Echo the result
echo «
" . print_r ( $result , true ). "
» ;
if( $result -> DeleteMarketplaceAdResult -> Status == «Success» )
<
echo «Item deleted!» ;
>
?>
There is a known bug with some versions of Xdebug which can cause SoapClient to not throw an exception but instead cause a fatal error.
Surround the SoapClient call with xdebug_disable(); and xdebug_enable(); to work around this problem.
If you are making soap calls in WSDL mode , and the address of your web service includes a port different from 80 (like http://my_ip_address:8080//service.asmx?wsdl), the WSDL file is fetched correctly, but all subsequent requests are made without any port in the host field. This causes a SoapFault exception when trying to call any of the service’s methods.
You need to redefine the soapClient class and force the port in each call.
CAUTION:
I had quite a bit of trouble trying to make a request with fopen through a proxy to a secure url. I kept getting a 400 Bad Request back from the remote host. It was receiving the proxy url as the SNI host. In order to get around this I had to explicity set the SNI host to the domain I was trying to reach. It’s apparently the issue outlined in this bug:
$domain = parse_url ( $file , PHP_URL_HOST );
$proxy_string = «tcp://» . WP_PROXY_HOST . «:» . WP_PROXY_PORT ;
$opts = array(
‘http’ => array( ‘proxy’ => $proxy_string ),
‘ssl’ => array( ‘SNI_enabled’ => true , ‘SNI_server_name’ => $domain ));
$context = stream_context_create ( $opts );
$handle = fopen ( $file , ‘r’ , false , $context );
?>
src:
http://php.net/manual/en/context.http.php#114314
If the XML have identities with same name in different levels there is a solution. You don´t have to ever submit a raw XML (this PHP SOAP object don´t allows send a RAW XML), so you have to always translate your XML to a array, like the example below:
//Translate the XML above in a array, like PHP SOAP function requires
$myParams = array(‘firstClient’ => array(‘name’ => ‘someone’,
‘adress’ => ‘R. 1001’),
‘secondClient’ => array(‘name’ => ‘another one’,
‘adress’ => »));
$webService = new SoapClient($someURL);
$result = $webService->someWebServiceFunction($myParams);
When you get errors like:
«Fatal error: Uncaught SoapFault exception: [HTTP] Error Fetching http headers in»
after a few (time intensive) SOAP-Calls, check your webserver-config.
Sometimes the webservers «KeepAlive»-Setting tends to result in this error. For SOAP-Environments I recommend you to disable KeepAlive.
Hint: It might be tricky to create a dedicated vhost for your SOAP-Gateways and disable keepalive just for this vhost because for normal webpages Keepalive is a nice speed-boost.
when they want to pass variables into the http header that is how it is done:
$aHTTP [ ‘http’ ][ ‘header’ ] = «User-Agent: PHP-SOAP/5.5.11\r\n» ;
$aHTTP [ ‘http’ ][ ‘header’ ].= «username: XXXXXXXXXXX\r\n» . «password: XXXXX\r\n» ;
$context = stream_context_create ( $aHTTP );
$result = $client -> jornadaActiva ();
var_dump ( $result );
?>
After migrating to PHP 5.6.5, the soap 1.2 did not work anymore. So I solved the problem by adding optional parameters SSL.
My error: failed to load external entity
How to solve:
// options for ssl in php 5.6.5
$opts = array(
‘ssl’ => array(‘ciphers’=>’RC4-SHA’, ‘verify_peer’=>false, ‘verify_peer_name’=>false)
);
// SOAP 1.2 client
$params = array (‘encoding’ => ‘UTF-8’, ‘verifypeer’ => false, ‘verifyhost’ => false, ‘soap_version’ => SOAP_1_2, ‘trace’ => 1, ‘exceptions’ => 1, «connection_timeout» => 180, ‘stream_context’ => stream_context_create($opts) );
$oSoapClient = new SoapClient ( $url . «?WSDL», $params );
Under IIS and PHP 7, when creating an new SoapClient, it will through an internal 500 error.
This could be caused by invalid permissions to the wsdl cache directory when using ‘cache_wsdl’=>WSDL_CACHE_DISK or WSDL_CACHE_BOTH.
This worked for me:
try $arrContextOptions=array(«ssl»=>array( «verify_peer»=>false, «verify_peer_name»=>false,’crypto_method’ => STREAM_CRYPTO_METHOD_TLS_CLIENT));
$options = array(
‘soap_version’=>SOAP_1_2,
‘exceptions’=>true,
‘trace’=>1,
‘cache_wsdl’=>WSDL_CACHE_NONE,
‘stream_context’ => stream_context_create($arrContextOptions)
);
$client = new SoapClient(‘https://url/dir/file.wsdl’, $options);
> catch (Exception $e) echo «
Exception Error!
«;
echo $e->getMessage();
>
In case a soap response returns nodes with the attribute xsi:nil=»false», they are currently not processed by php-soapclient.
This seems to be a bug (not correct).
class mySoapClient extends SoapClient public function __doRequest($request, $location, $action, $version, $one_way = 0) $response = parent::__doRequest($request, $location, $action, $version, $one_way);
$response = str_replace(‘xsi:nil=»false»‘,»»,$response);
return $response;
>
>
Took me a day. Hope it can help
Toppi
There is defined the server and the cliente who calls the web service.
I hope it would be useful for you.
To make an HTTPS call with a client certificate, you can do it this way:
1) Create a file containing both the key and the signed certificate. I did this by concatenating my (.pem) key and the certificate I’ve got signed from my CA (also .pem format). The file looked like this:
——BEGIN RSA PRIVATE KEY——
MIICXAIBAAKagQC1N27Ilb9pWil2NaX2qM8FquXBXK5T1AydOv7sCotsc8MAwbi7
. (snip).
wAiOCD4K9TyMS76pIS8UyfJl/oIrn7EF24BUpaUfsh8=
——END RSA PRIVATE KEY——
——BEGIN CERTIFICATE——
MIIC/zCCAmigAwIBAgIEAIl1JzANBgkqhkiG9w0BAQQuADBQMQswCQYxVQQGEaJV
. (snip).
eSPds1hLKYSg0bd3uI7LhaDLOC1PPgb77sYe/uYkUWuHBzllts5x/pfue0zaIBKG
Omjy
——END CERTIFICATE——
2) Reference your certificate in the creation of the SOAP client, like this:
$client = new SoapClient($protected_url, array(‘local_cert’, $my_cert_file) );
In addition to the KeepAlive trick which is a «server-side» modification, on the «client side» default_socket_timeout should be increased from its default value (60) when you deal with ~slow SOAP servers.
As for the KeepAlive, if creating a new separate vhost for the soap api is not possible, you can add this to your existing vhost: BrowserMatch «^PHP-SOAP» nokeepalive
where PHP-SOAP is the agent name of your soap client, if you dont know what agent name your client use, just checkout the access.log of your apache.
If you want to connect to a server that only supports SSLv2/3 and/or TLS 1.0 (no TLS 2 or 3), tell the SOAP client if you get a connection error by setting the appropriate stream context:
$opts = array(
‘ssl’ => array( ‘ciphers’ => ‘RC4-SHA’ )
);
$objSoapClient = new SoapClient (
‘https://example.com/?wsdl’ ,
array ( «encoding» => «ISO-8859-1» ,
‘stream_context’ => stream_context_create ( $opts )
// your options
);
?>
You might need to disable the SOAP caching of WSDLs in order for the SOAP client to use the new context.
This one drove me nuts. if you are connecting to a web service run on Cassini, (Visual Studio’s web server) from php, you may not be able to call web service functions or load a WSDL out-of-the-box.
My set up is that I am using xampp on my windows development machine, and also using Visual Studio’s built in web-server. I built a web service in visual studio. I wrote a simple PHP script, running under xampp, to access this service, so the two projects can ‘talk’ to each other. What I found was the WSDL was never loaded.
So I moved the WSDL local to the PHP file and accessed it directly. Still no calls. Turns out, PHP’s SoapClient seems to have a problem with ‘localhost’ as a web service endpoint. So I hand-edited the web service endpoint URL to read 127.0.0.1 instead of localhost, and Voila! Web Service calls work:
Here is my PHP, now working:
$client = new SoapClient ( «http://localhost/code/soap.wsdl» );
$something = $client -> HelloWorld (array());
echo $something -> HelloWorldResult ;
die();
Please note, that if you provide values that contain illegal xml characters (ASCII codes 0-8, 11-12, 14-15 — or x0-x8, xB-xC, xE-xF in hex), php’s SoapClient will do send them in request, although such request is improper because it does not meet XML 1.0 requirements.
You always have to replace or remove these characters in your data before supplying them to SoapClient
when they want to pass variables into the http header that is how it is done:
$aHTTP [ ‘http’ ][ ‘header’ ] = «User-Agent: PHP-SOAP/5.5.11\r\n» ;
$aHTTP [ ‘http’ ][ ‘header’ ].= «username: C1040001760102\r\n» . «password: bcv2020\r\n» ;
$context = stream_context_create ( $aHTTP );
$result = $client -> jornadaActiva ();
var_dump ( $result );
?>
I got the following error when trying to load the WSDL file:
Fatal error: Uncaught SoapFault exception: [WSDL] SOAP-ERROR: Parsing WSDL: ‘MessageName’ already defined
In my case there was no double definitions but it was including other files — I think one of them contained a duplicate message with a different namespace (which SoapClient doesn’t like).
I resolved it by loading the WSDL in SoapUI, right-clicking and selecting «Export definition». The WSDL that then got created worked fine. Hope this helps somebody.
Well, this example works fine:
try <
$x = @new SoapClient ( «non-existent.wsdl» );
> catch ( Exception $e ) <
echo $e -> getMessage ();
>
?>
Just make sure use NEW with @.
What is the core method to call remote WSDL file while creating SoapClient object?
is it CURL, wget or anyother?