SoapServer::handle

(PHP 5, PHP 7, PHP 8)

SoapServer::handle处理 SOAP 请求

说明

public SoapServer::handle(?string $request = null): void

处理 SOAP 请求,调用必要的函数,并发送响应。

参数

request

SOAP 请求。如果省略此参数,则请求被假定为在 HTTP 请求的原始 POST 数据中。

返回值

不返回值。

变更日志

版本 说明
8.0.0 request 现在可以为空。

示例

示例 #1 SoapServer::handle() 示例

<?php
function test($x)
{
return
$x;
}

$server = new SoapServer(null, array('uri' => "http://test-uri/"));
$server->addFunction("test");
$server->handle();
?>

参见

添加备注

用户贡献的备注 8 个备注

dub357 at gmail dot com
12 年前
经过一番头疼和查看 PHP 源代码后,我终于找到了 handle() 函数为什么会立即返回包含字符串“错误请求”的错误的原因。
事实证明我的客户端发送的是有效的 XML,但 XML 的第一行是实际的 XML 声明

<?xml version="1.0" encoding="UTF-8"?>

当调用 SoapServer 类中的“handle”函数时,它首先尝试解析 XML。当 XML 文档无法解析时,会返回“错误请求”错误,脚本执行立即停止。我假设 PHP 中内置的 XML 解析器 (libxml2) 已经假设该文档是 XML,当它找到声明时,它认为它无效。

我在调用 handle() 函数之前添加了一些 XML 解析调用来检查有效的 XML 以避免“错误请求”错误。这也允许我发送更合适的错误消息

<?php
$parser
= xml_parser_create("UTF-8");
if (!
xml_parse($parser,$HTTP_RAW_POST_DATA,true)){
$webService->fault("500", "Cannot parse XML: ".
xml_error_string(xml_get_error_code($parser)).
" at line: ".xml_get_current_line_number($parser).
", column: ".xml_get_current_column_number($parser));
}
?>
Bas van Dorst
10 年前
对“Joeri Thissen” (https://php.net/manual/en/soapserver.handle.php#113866) 评论的补充信息

在某些情况下,替换会生成超时(看起来是与 Nginx 结合使用)。问题是 PHP 已经发送了内容长度,而 Web 服务器仍在等待新内容。

要修复此问题,您必须使用正确的值重置 HTTP 内容长度

<?php
ob_start
();
$soapServer->handle();
$result = ob_get_contents();
ob_end_clean();

$result = str_replace("abcdef", "abc", $result);
$length = strlen($result);

header("Content-Length: ".$length);
echo
$result;
Joeri Thissen
10 年前
有时返回的数据可能包含在 xml 1.0 中无效的字符。这会导致 SoapServer::handle 输出的 xml 无效。尽管可能最好在更早的时候对数据进行清理,但可以结合使用输出缓冲区和一个简单的正则表达式作为快速修复,以确保输出确实是有效的 xml。

例如

<?php
ob_start
();
$soapServer->handle();
$soapXml = ob_get_contents();
ob_end_clean();
$soapXml = preg_replace ('/[^\x{0009}\x{000a}\x{000d}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}]+/u', ' ', $soapXml);
echo
$soapXml;
?>
Artur Graniszewski
14 年前
请注意,SoapServer::handle(); 方法会向浏览器发送额外的 HTTP 头。其中一个是“Content-Type: application/soap+xml”。如果您想作为 SoapClient::__doRequest() 的一部分在本地执行 SOAP 方法(请参阅 http://pl2.php.net/manual/en/soapclient.dorequest.php 中的示例),您可能需要将此头重置(覆盖)回“Content-Type: text/html”,如下所示

<?php
function Add($x,$y) {
return
$x+$y;
}

class
LocalSoapClient extends SoapClient {

function
__construct($wsdl, $options) {
parent::__construct($wsdl, $options);
$this->server = new SoapServer($wsdl, $options);
$this->server->addFunction('Add');
}

function
__doRequest($request, $location, $action, $version) {
ob_start();
$this->server->handle($request);
$response = ob_get_contents();
ob_end_clean();
return
$response;
}

}

$x = new LocalSoapClient(NULL,array('location'=>'test://',
'uri'=>'http://testuri.org'));

header("Content-Type: text/html");

var_dump($x->Add(3,4));

?>
Blizzke at gmail dot com
16 年前
找到解决方案后看起来很合乎逻辑,但我花了很长时间才弄明白。
如果你使用基于 WSDL 的 SOAP 请求,并且你的绑定中有多个操作(具有相同的参数),请确保 <soap:operation> 样式设置为 rpc,而不是 body!

当你在这里指定 'body' 时,请求中传输的将只是函数调用的参数,SoapServer->handle() 将使用它找到的第一个具有相同参数组合的函数来处理调用。

例如,如果你有两个函数
<?php
function One ( string $blah );
function
Two ( string $blah );
?>
使用 SoapClient -> Two ( 'test' ); 进行客户端调用,当你的 'type' 设置为 'body' 时,将会调用 One ( )。

只有当你的类型设置为 'rpc' 时,才会在请求中包含实际的调用方法,从而产生预期行为。
prenaud at profideo dot com
12 年前
请注意,当在一个 wsdl 文件中定义多个服务,并调用其中一个服务时,你可能总是收到第一个服务的响应。

这是一个已知的错误。你可以在这里找到它的描述和一些解决方法:https://bugs.php.net/bug.php?id=49169
tom at backslashinteractive dot com
15 年前
回复 Blizzke

有时,这个问题会隐藏在 Apache 分段错误和发送给客户端的 HTTP 头错误 SoapFault 中。

如果你遇到这两个错误中的任何一个,请尝试检查以确保你的 WSDL 文件的 soap:operation 中的 style="rpc" 设置正确。

-T
king dot maxemilian at noos dot fr
16 年前
有时,PHP 无法在 $HTTP_RAW_POST_DATA 中检测到任何内容。

要解决此问题并使其在任何情况下都能正常工作

function soaputils_autoFindSoapRequest() {
global $HTTP_RAW_POST_DATA;

if($HTTP_RAW_POST_DATA)
return $HTTP_RAW_POST_DATA;

$f = file("php://input");
return implode(" ", $f);
}

$server = new SoapServer($wsdl);
$server->setClass($MyClass);

$server->handle(soaputils_autoFindSoapRequest());
To Top