SoapClient

(PHP 5, PHP 7, PHP 8)

简介

SoapClient 类提供了一个针对 » SOAP 1.1, » SOAP 1.2 服务器的客户端。它可以在 WSDL 或非 WSDL 模式下使用。

类概要

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 $_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;
/* 方法 */
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 __getTypes(): ?array
public __setCookie(string $name, ?string $value = null): void
public __setLocation(?string $location = null): ?string
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

目录

添加笔记

用户贡献的笔记 20 notes

23
hugues at zonereseau dot com
13 年前
当您需要连接到需要发送额外标头的服务时,使用此方法。

以下是使用 PHP 和 SoapClient 的方法

<?php
class exampleChannelAdvisorAuth
{
public
$DeveloperKey;
public
$Password;

public function
__construct($key, $pass)
{
$this->DeveloperKey = $key;
$this->Password = $pass;
}
}

$devKey = "";
$password = "";
$accountId = "";

// 创建 SoapClient 实例
$url = "";
$client = new SoapClient($url, array("trace" => 1, "exception" => 0));

// 创建标头
$auth = new ChannelAdvisorAuth($devKey, $password);
$header = new SoapHeader("http://www.example.com/webservices/", "APICredentials", $auth, false);

// 调用 wsdl 函数
$result = $client->__soapCall("DeleteMarketplaceAd", array(
"DeleteMarketplaceAd" => array(
"accountID" => $accountId,
"marketplaceAdID" => "9938745" // 广告 ID
)
),
NULL, $header);

// 回显结果
echo "<pre>".print_r($result, true)."</pre>";
if(
$result->DeleteMarketplaceAdResult->Status == "Success")
{
echo
"商品已删除!";
}
?>
2
Stefan
10 年前
某些版本的 Xdebug 存在已知错误,会导致 SoapClient 不会抛出异常,而是引发致命错误。

将 SoapClient 调用包含在 xdebug_disable(); 和 xdebug_enable(); 之间,以解决此问题。

参考

http://bugs.xdebug.org/view.php?id=249
https://bugs.php.net/bug.php?id=47584
2
peter dot hansen at fastit dot net
15 年前
当你遇到类似于
"致命错误:未捕获的 SoapFault 异常: [HTTP] 获取 http 头部错误"
在几次(耗时的)SOAP 调用之后,检查你的 web 服务器配置。

有时 web 服务器的 "KeepAlive" 设置会导致此错误。对于 SOAP 环境,我建议你禁用 KeepAlive。

提示:为你的 SOAP 网关创建一个专门的虚拟主机并只为该虚拟主机禁用 keepalive 可能很棘手,因为对于普通的网页,KeepAlive 是一个很好的速度提升。
0
info at nospam x valiton x com
9 年前
注意
我尝试通过代理向安全 URL 发起 fopen 请求时遇到了一些麻烦。我一直收到来自远程主机的 400 错误请求。它接收代理 URL 作为 SNI 主机。为了解决这个问题,我不得不显式地将 SNI 主机设置为我尝试访问的域名。这显然是此错误中概述的问题

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

来源
https://php.net/manual/en/context.http.php#114314
-1
jjlopez
13 年前
如果你正在 WSDL 模式下进行 soap 调用,并且你的 web 服务地址包含一个与 80 不同的端口(例如 http://my_ip_address:8080//service.asmx?wsdl),WSDL 文件会正确获取,但所有后续请求都在主机字段中不带任何端口进行。这会导致在尝试调用服务的任何方法时出现 SoapFault 异常。

你需要重新定义 soapClient 类,并在每次调用中强制指定端口。

请查看此示例

http://www.victorstanciu.ro/php-soapclient-port-bug-workaround/
-3
Ricardo Pedrassani
8 年前
如果 XML 中的不同级别包含相同名称的标识,则有一个解决方案。你永远不需要提交原始 XML(这个 PHP SOAP 对象不允许发送原始 XML),所以你必须始终将你的 XML 转换为数组,如下面的示例所示

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

// 将上面的 XML 转换为数组,就像 PHP SOAP 函数要求的那样
$myParams = array('firstClient' => array('name' => 'someone',
'adress' => 'R. 1001'),
'secondClient' => array('name' => 'another one',
'adress' => ''));

$webService = new SoapClient($someURL);
$result = $webService->someWebServiceFunction($myParams);
-3
acopantepuy at gmail dot com
9 年前
当他们想要将变量传递到 http 头部时,就是这样做的

<?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);
?>
-7
romuloum at hotmail dot com
9 年前
迁移到 PHP 5.6.5 后,soap 1.2 无法正常工作。因此,我通过添加可选参数 SSL 来解决此问题。
我的错误:无法加载外部实体
解决方法
// PHP 5.6.5 中的 ssl 选项
$opts = array(
'ssl' => array('ciphers'=>'RC4-SHA', 'verify_peer'=>false, 'verify_peer_name'=>false)
);
// SOAP 1.2 客户端
$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 );
-1
spam at kacke dot de
1 年前
如果 soap 响应返回具有 xsi:nil="false" 属性的节点,则当前不会由 php-soapclient 处理。

这似乎是一个错误(不正确)。

解决方法

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;
}
}

花了我一天的时间。希望它能有所帮助
Toppi
-8
David
7 年前
在 IIS 和 PHP 7 下,创建新的 SoapClient 时,它将引发内部 500 错误。

这可能是因为在使用 'cache_wsdl'=>WSDL_CACHE_DISK 或 WSDL_CACHE_BOTH 时,对 wsdl 缓存目录的权限无效。

这对我有用
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>异常错误!</h2>";
echo $e->getMessage();
}
-13
Guillermo Prandi
12 年前
要使用客户端证书进行 HTTPS 调用,你可以按照以下步骤操作

1) 创建一个包含密钥和签名证书的文件。我通过将我的 (.pem) 密钥和从我的 CA 签名的证书(也是 .pem 格式)连接在一起来做到这一点。该文件如下所示

-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKagQC1N27Ilb9pWil2NaX2qM8FquXBXK5T1AydOv7sCotsc8MAwbi7
......(snip)......
wAiOCD4K9TyMS76pIS8UyfJl/oIrn7EF24BUpaUfsh8=
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIC/zCCAmigAwIBAgIEAIl1JzANBgkqhkiG9w0BAQQuADBQMQswCQYxVQQGEaJV
......(snip)......
eSPds1hLKYSg0bd3uI7LhaDLOC1PPgb77sYe/uYkUWuHBzllts5x/pfue0zaIBKG
Omjy
-----END CERTIFICATE-----

2) 在创建 SOAP 客户端时引用你的证书,如下所示

$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) );
-10
softontherocks at gmail dot com
9 年前
我在这个 URL 上发布了一个完整的使用 nusoap web 服务的示例 http://softontherocks.blogspot.com/2014/02/web-service-soap-con-php.html

其中定义了服务器和调用 web 服务的客户端。

我希望这对您有所帮助。
-6
mcinantyspam at fejm dot pl
8 年前
请注意,如果你提供包含非法 xml 字符(ASCII 码 0-8、11-12、14-15 - 或十六进制的 x0-x8、xB-xC、xE-xF)的值,php 的 SoapClient 会将它们发送到请求中,尽管这样的请求是不正确的,因为它不符合 XML 1.0 要求。
在将数据提供给 SoapClient 之前,你必须始终替换或删除这些字符。
-13
egiardina at badatmath dot com
13 年前
这个把我搞得焦头烂额......如果你正在从 php 连接到在 Cassini(Visual Studio 的 web 服务器)上运行的 web 服务,你可能无法开箱即用地调用 web 服务函数或加载 WSDL。

我的设置是我在我的 Windows 开发机器上使用 xampp,并且还使用 Visual Studio 内置的 web 服务器。我在 Visual Studio 中构建了一个 web 服务。我编写了一个简单的 PHP 脚本,在 xampp 下运行,来访问此服务,以便这两个项目可以相互 "通信"。我发现 WSDL 从未加载。

因此,我将 WSDL 移动到 PHP 文件的本地位置并直接访问它。仍然无法调用。事实证明,PHP 的 SoapClient 似乎对 "localhost" 作为 web 服务端点存在问题。因此,我手动编辑了 web 服务端点 URL,使其读取 127.0.0.1 而不是 localhost,然后就成功了!web 服务调用可以正常工作了

这是我的 PHP 代码,现在可以正常工作了
<?php
$client
= new SoapClient("http://localhost/code/soap.wsdl");
$something = $client->HelloWorld(array());
echo
$something->HelloWorldResult;
die();

?>

以下是修改后的 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>
-13
martin dot schenck at plugsurfing dot com
9 年前
如果你想要连接到一个只支持 SSLv2/3 和/或 TLS 1.0(不支持 TLS 2 或 3)的服务器,并在连接错误时通知 SOAP 客户端,请设置相应的流上下文。
<?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)
// 你的选项
);
?>

你可能需要禁用 SOAP 对 WSDL 的缓存,以便 SOAP 客户端使用新的上下文。
-13
fourat dot zouari at tritux dot com
15 年前
除了 KeepAlive 技巧,它是一个“服务器端”的修改,在“客户端”方面,当你处理速度较慢的 SOAP 服务器时,应该将 default_socket_timeout 从其默认值(60)增加。
对于 KeepAlive,如果无法为 SOAP API 创建新的独立虚拟主机,你可以在现有的虚拟主机中添加以下内容: BrowserMatch "^PHP-SOAP" nokeepalive
其中 PHP-SOAP 是你的 SOAP 客户端的代理名称,如果你不知道你的客户端使用的是哪个代理名称,只需查看你的 apache 的 access.log。
-26
Anonymous
10 年前
在尝试加载 WSDL 文件时,我遇到了以下错误

致命错误:未捕获的 SoapFault 异常: [WSDL] SOAP-ERROR:解析 WSDL: <message> 'MessageName' 已定义

在我的案例中,没有重复定义,但它正在包含其他文件 - 我认为其中一个文件包含了一个具有不同命名空间的重复消息(SoapClient 不喜欢这种方式)。

我通过在 SoapUI 中加载 WSDL,右键单击并选择“导出定义”来解决这个问题。然后创建的 WSDL 就可以正常工作了。希望这能帮助到某些人。
-20
acopantepuy at gmail dot com
9 年前
当他们想要将变量传递到 http 头部时,就是这样做的

<?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);
?>
-32
stepan dot zarubin at gmail dot com
13 年前
嗯,这个例子工作正常

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

只要确保使用 NEW 和 @ 即可。
-45
sheikh303 at gmail dot com
7 年前
创建 SoapClient 对象时,调用远程 WSDL 文件的核心方法是什么?
是 CURL、wget 还是其他方法?
To Top