使用PHP解析实时SOAP数据流

Joe*_*wis 12 php soap

我有一个企业应用程序,它提供了一个相当强大的API来收集数据.目前,我每秒都在循环中查询每个用户.但是,新的API文档现在提供了所有用户的所有更改的实时流.我想知道如何解析这个实时数据,因为它附带了PHP.以下是一些细节:

通过SOAP请求请求数据,我使用PHP来发出这样的请求(会话启动示例返回唯一ID):

//Get a session ID for this user for the shoretel WEBAPI
$soap_url = 'http://11.11.11.11:8070/ShoreTelWebSDK?wsdl';
$client = new SOAPClient($soap_url, array( 'proxy_host' => '11.11.11.11', 'proxy_port' => 8070, 'trace' => 1 ) );
$client = new SoapClient($soap_url);

$header = new SoapHeader('http://www.ShoreTel.com/ProServices/SDK/Web');
$client->__setSoapHeaders($header);
$registered_string = $client->RegisterClient(array(
                'clientName' => '11.11.11.211'
            )); 
$registered_string = get_object_vars($registered_string);   
$session =  $registered_string['RegisterClientResult'];
Run Code Online (Sandbox Code Playgroud)

新方法允许我指定时间段.例如,如果我希望所有事件都持续1分钟,则会启动呼叫,等待一分钟,然后返回该分钟内发生的所有事件.

我想要做的是抓住每个事件,并将其插入数据库.这是我可以用PHP完成的事情,还是我需要寻找另一种语言才能实现这一目标?

Jen*_*och 3

好的,目标是在“超时”和/或“间隔”内“传输 SOAP 响应”?

我建议重写该SoapClient __doRequest()方法并通过 实现自定义连接fsockopen()并使用stream_get_contents(). 现在您获得了 XML 数据流,而您想要的内容就在其中。您必须提取 XML 信封或其中的一部分,可能使用字符串函数或使用preg_match来获取内部内容。

以下代码提供了一个 SoapClientTimeout 类,其中超时通过stream_set_timeout(). 这是针对服务器响应缓慢并且您想要确定何时结束监听的用例。

我建议尝试一下并调整套接字上的超时行为。因为,您想要的是在一段时间后停止监听(间隔获取)。因此,您尝试将超时与阻塞结合起来,在一段时间后停止从流中读取:

$timeout = 60; // seconds
stream_set_blocking($socket, true);
stream_set_timeout($socket, $timeout); 
Run Code Online (Sandbox Code Playgroud)

当您有一个流在 1 分钟后阻塞并关闭时,您需要一个循环(具有可靠的退出条件)来触发下一个请求。


class SoapClientTimeout extends SoapClient
{    
    public function __construct ($wsdl, $options = null)
    {
        if (!$options) $options = [];

        $this->_connectionTimeout = @$options['connection_timeout'] ?: ini_get ('default_socket_timeout');
        $this->_socketTimeout = @$options['socket_timeout'] ?: ini_get ('default_socket_timeout');
        unset ($options['socket_timeout']);

        parent::__construct($wsdl, $options);
    }

    /**
     * Override parent __doRequest and add "timeout" functionality.
     */
    public function __doRequest ($request, $location, $action, $version, $one_way = 0)
    {
        // fetch host, port, and scheme from url.
        $url_parts = parse_url($location);

        $host = $url_parts['host'];
        $port =  @$url_parts['port'] ?: ($url_parts['scheme'] == 'https' ? 443 : 80);
        $length = strlen ($request);

        // create HTTP SOAP request.
        $http_req = "POST $location HTTP/1.0\r\n";
        $http_req .= "Host: $host\r\n";
        $http_req .= "SoapAction: $action\r\n";
        $http_req .= "Content-Type: text/xml; charset=utf-8\r\n";
        $http_req .= "Content-Length: $length\r\n";
        $http_req .= "\r\n";
        $http_req .= $request;

        // switch to SSL, when requested
        if ($url_parts['scheme'] == 'https') $host = 'ssl://'.$host;

        // connect
        $socket = @fsockopen($host, $port, $errno, $errstr, $this->_connectionTimeout);

        if (!$socket) {
            throw new SoapFault('Client',"Failed to connect to SOAP server ($location): $errstr");
        }

        // send request with socket timeout
        stream_set_timeout($socket, $this->_socketTimeout);
        fwrite ($socket, $http_req);

        // start reading the response.
        $http_response = stream_get_contents($socket);

        // close the socket and throw an exception if we timed out.
        $info = stream_get_meta_data($socket);
        fclose ($socket);
        if ($info['timed_out']) {
            throw new SoapFault ('Client', "HTTP timeout contacting $location");
        }

        // the stream contains XML data
        // lets extract the XML from the HTTP response and return it.
        $response = preg_replace (
            '/
                \A       # Start of string
                .*?      # Match any number of characters (as few as possible)
                ^        # Start of line
                \r       # Carriage Return
                $        # End of line
             /smx',
            '', $http_response
        );
        return $response;
    }

}
Run Code Online (Sandbox Code Playgroud)