【问题标题】:SoapServer, fault on handle() - Procedure not setSoapServer,handle() 故障 - 未设置程序
【发布时间】:2026-01-25 00:55:02
【问题描述】:

所以错误是:

PHP Fatal error: Procedure 'sup:set_availability' not present in XMLSoapServer.php

我在开发环境 (MAMP) 上收到此错误。

这是由无效的 XML 字符串引起的,其中未定义 'sup' 命名空间:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<SOAP-ENV:Envelope xmlns:SOAPSDK1="http://www.w3.org/2001/XMLSchema" 
    xmlns:SOAPSDK2="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:SOAPSDK3="http://schemas.xmlsoap.org/soap/encoding/" 
    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <SOAP-ENV:Body>
        <sup:set_availability>
            <SetAvailability>
                ...
            </SetAvailability>
        </sup:set_availability>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

(这是一个外部请求,所以我不能只是去纠正来源 - 我可以,但至少不是在短时间内。)

问题是我有 2 台服务器正在处理相同的请求。没有错误。所以我的任务是找出原因:)

一些细节:

  • 服务器 1:php 5.3.2
  • 服务器 2:php 5.4
  • 开发:php 5.4

到目前为止我检查过的事情:

  • 代码是一样的svn-checkout
  • 没有隐藏的开发或仅生产设置
  • apache 配置是一样的
  • wsdl 缓存被禁用,缓存的 wsdl 被清除
  • php.ini 设置相同,libxml2 除外:

服务器 1 的版本为 2.6.26 服务器 2 的版本为 2.7.7 - 请求在该版本上运行就像一个魅力 我的开发环境有 lixml2 版本 2.8.0 - 并且确实抛出了致命错误。

我的猜测是(或曾经是)libxml2 导致了错误 - 但我找不到有关此主题的任何资源 - 我也没有成功将本地 libxml2 版本降级到 2.6 或 2.7。

那么...对此有什么想法吗?

【问题讨论】:

  • 您是否在所有 3 台服务器上或仅在您的开发服务器上禁用缓存并清除缓存的 wsdl?也许服务器 1 和 2 正在使用不存在此问题的缓存版本?
  • 在两台服务器上禁用清除;没有解决问题。

标签: php fault soapserver


【解决方案1】:

我不知道问题出在哪里......但是由于原生 PHP SoapClient 对我来说总是有点“不透明”,所以我喜欢使用 Dklab_SoapClient library

它使用 Curl 来检索 Soap 数据,它比原生 PHP 类灵活得多。 另外,如果您也需要,您甚至可以扩展它以添加您自己的功能:) 我猜它会解决你的问题。

但是,如果您不想使用外部库,我不知道是什么原因造成的......

【讨论】:

  • 这不是关于客户端,而是关于服务器。
  • 确实,它(可能)是服务器。而且由于这是一个大/复杂框架的一部分,我不能轻易替换这些类......
【解决方案2】:

我认为缺少传递给soap客户端的变量。检查soap客户端是否工作

【讨论】:

  • 不,不是客户端。
【解决方案3】:

我会建议一个不同的角度来解决这个问题。

您可以在将请求提供给 XML 解析器之前修改请求,而不是破坏您的 XML 解析器。如果请求不存在,请将 sup 命名空间添加到请求中。最好将此更改推送到生产并更新/修复您的生产 XML 解析器。

一旦外部来源使他们的软件正常工作,请删除此 hack。

【讨论】:

  • 我忘了说;除了 'sup' 命名空间之外,还有多个(如 20 到 30 个)命名空间错误,例如 sup 错误。因此,添加所有这些异常并不是一件好事。用户“hakre”也在展示这个解决方案;它有效,但不是最有利的做法。
【解决方案4】:

这听起来像是服务器配置的问题。 WSDL URI 对于您的开发机器可能是错误的,因此当 soapserver 自省到 WSDL 时,它无法找到该函数,因为它正在查找错误的服务器。

XML 仍然是错误的,因为名称空间前缀仍未定义。我不希望它安全地工作,因为这不是有效的 XML,并且 SOAP 工作需要有效的 XML。

使用 LIBXML 2.9.1 进行的快速测试显示,DOMDocument 加载了错误的 XML 块,并带有警告但保留(包括前缀)。如果您可以访问底层请求文档,则可以自己添加:

// just test code to mock a DOMDocument having the fault XML from question
$doc  = new DOMDocument();
$back = libxml_use_internal_errors(TRUE);
$doc->loadXML($xml);
libxml_use_internal_errors($back);

// poc to add the prefix definition
$doc->documentElement->setAttributeNS(
    'http://www.w3.org/2000/xmlns/', 'xmlns:sup', 'sup:uri'
);

那么文档是:

<SOAP-ENV:Envelope xmlns:SOAPSDK1="http://www.w3.org/2001/XMLSchema" 
        xmlns:SOAPSDK2="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns:SOAPSDK3="http://schemas.xmlsoap.org/soap/encoding/" 
        xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
        xmlns:sup="sup:uri">
    <SOAP-ENV:Body>
        <sup:set_availability>
            <SetAvailability>
                ...
            </SetAvailability>
        </sup:set_availability>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

如您所见,前缀定义已添加。可以在SoapServer::handle()之前拦截进来的请求,修改后注入handle($soap_request)

  • SOAP 操作:$_SERVER['HTTP_SOAPACTION']
  • 请求正文:file_get_contents( 'php://input')
  • 见:SoapServer::handle()

【讨论】: