略微加速

PHP官方手册 - 互联网笔记

PHP - Manual: SoapClient

2024-11-14

The SoapClient class

(PHP 5, PHP 7, PHP 8)

简介

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 SoapClient {
/* 属性 */
private ?string $uri = null;
private ?int $style = null;
private ?int $use = null;
private ?string $location = null;
private bool $trace = false;
private ?int $compression = null;
private ?resource $sdl = null;
private ?resource $typemap = null;
private ?resource $httpsocket = null;
private ?resource $httpurl = null;
private ?string $_login = null;
private ?string $_password = null;
private bool $_use_digest = false;
private ?string $_digest = null;
private ?string $_proxy_host = null;
private ?int $_proxy_port = null;
private ?string $_proxy_login = null;
private ?string $_proxy_password = null;
private bool $_exceptions = true;
private ?string $_encoding = null;
private ?array $_classmap = null;
private ?int $_features = null;
private ?resource $_stream_context = null;
private ?string $_user_agent = null;
private bool $_keep_alive = true;
private ?int $_ssl_method = null;
private int $_soap_version;
private ?int $_use_proxy = null;
private array $_cookies = [];
private ?array $__default_headers = null;
private ?SoapFault $__soap_fault = null;
private ?string $__last_request = null;
private ?string $__last_response = null;
private ?string $__last_request_headers = null;
private ?string $__last_response_headers = null;
/* 方法 */
public __construct(?string $wsdl, array $options = [])
public __call(string $name, array $args): mixed
public __doRequest(
    string $request,
    string $location,
    string $action,
    int $version,
    bool $oneWay = false
): ?string
public __getCookies(): array
public __getFunctions(): ?array
public __getLastRequest(): ?string
public __getLastRequestHeaders(): ?string
public __getLastResponse(): ?string
public __getLastResponseHeaders(): ?string
public __getTypes(): ?array
public __setCookie(string $name, ?string $value = null): void
public __setLocation(?string $location = null): ?string
public __setSoapHeaders(SoapHeader|array|null $headers = null): bool
public __soapCall(
    string $name,
    array $args,
    ?array $options = null,
    SoapHeader|array|null $inputHeaders = null,
    array &$outputHeaders = null
): mixed
}

属性

__default_headers

__last_request

__last_request_headers

__last_response

__last_response_headers

__soap_fault

_classmap

_connection_timeout

_cookies

_digest

_encoding

_exceptions

_features

_keep_alive

_login

_password

_proxy_host

_proxy_login

_proxy_password

_proxy_port

_soap_version

_ssl_method

_stream_context

_use_digest

_use_proxy

_user_agent

compression

httpsocket

httpurl

location

sdl

style

trace

typemap

uri

use

目录

add a noteadd a note

User Contributed Notes 19 notes

up
23
hugues at zonereseau dot com
11 years ago
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

<?php
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 "<pre>".print_r($result, true)."</pre>";
if(
$result->DeleteMarketplaceAdResult->Status == "Success")
{
    echo
"Item deleted!";
}
?>
up
0
info at nospam x valiton x com
7 years ago
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:

https://bugs.php.net/bug.php?id=63519

<?php
$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
up
0
jjlopez
11 years ago
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.

See this example:

http://www.victorstanciu.ro/php-soapclient-port-bug-workaround/
up
-1
Stefan
8 years ago
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.

For reference:

http://bugs.xdebug.org/view.php?id=249
https://bugs.php.net/bug.php?id=47584
up
0
peter dot hansen at fastit dot net
13 years ago
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.
up
-2
acopantepuy at gmail dot com
7 years ago
when they want to pass variables into the http header that is how it is done:

<?php

$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);

$client=new SoapClient("https://ocppws-cert.extra.bcv.org.ve:443/AltoValor/BancoUniversal?WSDL",array('trace' => 1,"stream_context" => $context));

$result = $client->jornadaActiva();
var_dump($result);
?>
up
-3
Ricardo Pedrassani
6 years ago
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:

$originalXML = "
<xml>
  <firstClient>
      <name>someone</name>
      <adress>R. 1001</adress>
  </firstClient>
  <secondClient>
      <name>another one</name>
      <adress></adress>
  </secondClient>
</xml>"

//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);
up
-8
romuloum at hotmail dot com
7 years ago
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 );
up
-7
David
5 years ago
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 "<h2>Exception Error!</h2>";
        echo $e->getMessage();
    }
up
-7
martin dot schenck at plugsurfing dot com
7 years ago
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:
<?php
  $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.
up
-8
softontherocks at gmail dot com
7 years ago
I posted in this URL http://softontherocks.blogspot.com/2014/02/web-service-soap-con-php.html a full example of a nusoap web service.

There is defined the server and the cliente who calls the web service.

I hope it would be useful for you.
up
-8
fourat dot zouari at tritux dot com
13 years ago
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.
up
-13
Guillermo Prandi
10 years ago
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:

$protected_url = "https://my-server/?wsdl";
$my_cert_file = "/my/path/to/mycert.pem";

$client = new SoapClient($protected_url, array('local_cert', $my_cert_file) );
up
-6
mcinantyspam at fejm dot pl
6 years ago
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
up
-15
egiardina at badatmath dot com
10 years ago
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:
<?php
$client
= new SoapClient("http://localhost/code/soap.wsdl");
$something $client->HelloWorld(array());
echo
$something->HelloWorldResult;
die();

?>

Here is my modified WSDL:
  <wsdl:service name="MyService">
    <wsdl:port name="MyServiceSoap" binding="tns:MyServiceSoap">
      <soap:address location="http://127.0.0.1:55274/MyService/MyService.asmx" />
....

    </wsdl:port>
up
-23
Anonymous
8 years ago
I got the following error when trying to load the WSDL file:

Fatal error: Uncaught SoapFault exception: [WSDL] SOAP-ERROR: Parsing WSDL: <message> '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.
up
-18
acopantepuy at gmail dot com
7 years ago
when they want to pass variables into the http header that is how it is done:

<?php

$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);

$client=new SoapClient("https://ocppws-cert.extra.bcv.org.ve:443/AltoValor/BancoUniversal?WSDL",array('trace' => 1,"stream_context" => $context));

$result = $client->jornadaActiva();
var_dump($result);
?>
up
-24
stepan dot zarubin at gmail dot com
10 years ago
Well, this example works fine:

<?php
try { 
   
$x = @new SoapClient("non-existent.wsdl"); 
} catch (
Exception $e) { 
    echo
$e->getMessage();
}
?>

Just make sure use NEW with @.
up
-33
sheikh303 at gmail dot com
5 years ago
What is the core method to call remote WSDL file while creating SoapClient object?
is it CURL, wget or anyother?

官方地址:https://www.php.net/manual/en/class.soapclient.php

北京半月雨文化科技有限公司.版权所有 京ICP备12026184号-3