35

无论如何,SoapClient 请求是否会超时并引发异常。截至目前,我得到 PHP 服务器响应超时,在我的情况下为 60 秒。基本上我想要的是,如果在特定时间内没有来自 Web 服务的任何回复,则会抛出异常并且我可以捕获它。60 秒的警告不是我想要的。

4

7 回答 7

61

无效的答案。请参阅https://stackoverflow.com/a/12119215/441739


虽然 Andrei 链接到了一个不错的解决方案,但这个解决方案的代码更少,但却得到了一个很好的解决方案:

*使用 PHP5 SoapClient 扩展处理超时(Antonio Ramirez;2010 年 2 月 2 日)
示例代码:
//
// 设置连接超时(十五秒)在示例上)
//
$client = new SoapClient($wsdl, array("connection_timeout" => 15));
如果您需要更细粒度的 HTTP 控制,还有流上下文。请参阅Docsstream_context的选项。在表面之下使用 HTTP 和 SSL 传输。new SoapClient()SoapClient

于 2012-05-07T15:50:41.137 回答
59
ini_set("default_socket_timeout", 15);
$client = new SoapClient($wsdl, array(......));

connection_timeout 选项定义了连接到 SOAP 服务的超时时间(以秒为单位)。此选项不为响应缓慢的服务定义超时。为了限制等待调用完成的时间,可以使用 default_socket_timeout 设置。

于 2012-08-25T04:41:34.630 回答
17

看一下

如果您感到舒适并且您的环境允许您扩展课程。

它基本上扩展了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);
        }
    }
}
于 2010-08-17T08:17:40.277 回答
8

接受的答案将破坏 SoapClient 必须提供的所有功能。比如设置正确的内容标题、身份验证等。

这将是解决问题的更好方法

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

}
于 2016-05-13T14:42:12.053 回答
2

您可以通过 composer 安装它: https ://github.com/ideaconnect/idct-soap-client

它扩展了标准 SoapClient 并提供了设置重试次数、连接和读取超时的选项。

于 2014-03-27T12:04:31.073 回答
1

我在使用 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;
}

这有助于我等待长达 10 秒的连接建立和 60 秒的调用执行时间。

于 2018-12-06T10:46:36.967 回答
1

您还可以使用stream_context_create()并将timeout选项添加到http数组中:

$context = stream_context_create(
    array(
        'http' => array(
            "timeout" => 10,
        ),
    )
);

这是PHP手册页

SoapHandler 初始化应该是:

$soapHandler = new SoapClient($wsdl, [
    //more params, if needed..
    
    'stream_context' => $context,
]);
于 2021-08-24T21:10:15.197 回答