PHP SoapClient 超时
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3500527/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
PHP SoapClient Timeout
提问by Shamim Hafiz
Is there anyway for a SoapClient Request to time out and throw an exception. As of now, I get PHP Server response timeout, in my case 60 seconds. Basically what I want is, if there isn't any reply from the Web Service within certain time, an exception would be thrown and I could catch it. The 60 seconds warning is not what I want.
无论如何,SoapClient 请求是否超时并抛出异常。截至目前,我收到 PHP 服务器响应超时,在我的情况下为 60 秒。基本上我想要的是,如果在特定时间内没有来自 Web 服务的任何回复,则会抛出异常并且我可以捕获它。60 秒警告不是我想要的。
采纳答案by Andrei Serdeliuc ?
Have a look at
看一下
if you are comfortable and your environment allows you to extend classes.
如果您感觉舒适并且您的环境允许您扩展课程。
It basically extends the SoapClient
class, replaces the HTTP transport with curl which can handle the timeouts:
它基本上扩展了SoapClient
类,用可以处理超时的 curl 替换了 HTTP 传输:
class SoapClientTimeout extends SoapClient
{
private $timeout;
public function __setTimeout($timeout)
{
if (!is_int($timeout) && !is_null($timeout))
{
throw new Exception("Invalid timeout value");
}
$this->timeout = $timeout;
}
public function __doRequest($request, $location, $action, $version, $one_way = FALSE)
{
if (!$this->timeout)
{
// Call via parent because we require no timeout
$response = parent::__doRequest($request, $location, $action, $version, $one_way);
}
else
{
// Call via Curl and use the timeout
$curl = curl_init($location);
curl_setopt($curl, CURLOPT_VERBOSE, FALSE);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_POST, TRUE);
curl_setopt($curl, CURLOPT_POSTFIELDS, $request);
curl_setopt($curl, CURLOPT_HEADER, FALSE);
curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-Type: text/xml"));
curl_setopt($curl, CURLOPT_TIMEOUT, $this->timeout);
$response = curl_exec($curl);
if (curl_errno($curl))
{
throw new Exception(curl_error($curl));
}
curl_close($curl);
}
// Return?
if (!$one_way)
{
return ($response);
}
}
}
回答by Jon L.
While Andrei linked to a decent solution, this one has less code yet arrives at a good solution:
虽然 Andrei 链接到了一个不错的解决方案,但这个解决方案的代码较少,但得出了一个很好的解决方案:
Example code:
示例代码:
//
// setting a connection timeout (fifteen seconds on the example)
//
$client = new SoapClient($wsdl, array("connection_timeout" => 15));
And there is also the stream context, if you need more fine-grained HTTP control. See the stream_context
option for new SoapClient()
Docs. Under the surface SoapClient
uses the HTTP and SSL transports.
如果您需要更细粒度的 HTTP 控制,还有流上下文。请参阅Docsstream_context
选项。在表面之下使用 HTTP 和 SSL 传输。new SoapClient()
SoapClient
回答by gdtv
ini_set("default_socket_timeout", 15);
$client = new SoapClient($wsdl, array(......));
The connection_timeout option defines a timeout in seconds for the connection to the SOAP service. This option does not define a timeout for services with slow responses. To limit the time to wait for calls to finish the default_socket_timeout setting is available.
connection_timeout 选项以秒为单位定义连接到 SOAP 服务的超时时间。此选项不会为响应缓慢的服务定义超时。为了限制等待调用完成的时间,可以使用 default_socket_timeout 设置。
回答by Sander Visser
The accepted answer will break all functionalities that SoapClient has to offer. Like setting the correct content headers, authentication etc.
接受的答案将破坏 SoapClient 必须提供的所有功能。像设置正确的内容标题,身份验证等。
This would be a better solution to the problem
这将是解决问题的更好方法
class MySoapClient extends \SoapClient
{
private $timeout = 10;
public function __construct($wsdl, array $options)
{
// Defines a timeout in seconds for the connection to the SOAP service.
// This option does not define a timeout for services with slow responses.
// To limit the time to wait for calls to finish the default_socket_timeout setting is available.
if (!isset($options['connection_timeout'])) {
$options['connection_timeout'] = $this->timeout;
}
parent::__construct($wsdl, $options);
}
public function setTimeout($timeout)
{
$this->timeout = $timeout;
}
public function __doRequest($request, $location, $action, $version, $one_way = 0)
{
$original = ini_get('default_socket_timeout');
ini_set('default_socket_timeout', $this->timeout);
$response = parent::__doRequest($request, $location, $action, $version, $one_way);
ini_set('default_socket_timeout', $original);
return $response;
}
}
回答by Bartosz Pacho?ek
You can install this through composer: https://github.com/ideaconnect/idct-soap-client
您可以通过 composer 安装它:https: //github.com/ideaconnect/idct-soap-client
It extends the standard SoapClient and gives options to set the amount of retries, connection and read timeouts.
它扩展了标准的 SoapClient,并提供了设置重试次数、连接和读取超时的选项。
回答by Dmytro Lukachuk
I am using the following logic when working with SOAPClient:
使用 SOAPClient 时,我使用以下逻辑:
public function executeSoapCall($method, $params)
{
try {
$client = $this->tryGetSoapClient();
$timeout = ini_get('default_socket_timeout');
ini_set('default_socket_timeout', 60);//set new timeout value - 60 seconds
$client->__soapCall($method, $params);//execute SOAP call
ini_set('default_socket_timeout', $timeout);//revert timeout back
} catch (\Throwable $e) {
if (isset($timeout)) {
ini_set('default_socket_timeout', $timeout);//revert timeout back
}
}
}
protected function tryGetSoapClient()
{
$timeout = ini_get('default_socket_timeout');//get timeout (need to be reverted back afterwards)
ini_set('default_socket_timeout', 10);//set new timeout value - 10 seconds
try {
$client = new \SoapClient($this->wsdl, $this->options);//get SOAP client
} catch (\Throwable $e) {
ini_set('default_socket_timeout', 10);//revert back in case of exception
throw $e;
}
$this->iniSetTimeout($timeout);//revert back
return $client;
}
This helps me to wait up to 10 seconds for connection establishment, and 60 seconds for the call execution.
这有助于我等待最多 10 秒的连接建立时间和 60 秒的调用执行时间。