【问题标题】:Serializing a PHP SOAPClient object序列化 PHP SOAPClient 对象
【发布时间】:2011-03-23 14:34:56
【问题描述】:

我正在编写一个 PHP 应用程序,它使用许多 SOAP Web 服务来收集数据。

我在实例化所有这些对象时获得了巨大的开销:在某些情况下,一行代码$object = new SoapClient($wsdl); 可能需要三秒钟以上的时间。显然,只需要其中几个就可以让网页感觉非常慢。

为了加快速度,我想我会序列化对象并将它们存储在会话中(或类似的地方),所以我编写了以下函数:

function soap_client($name,$wsdl) {
    if (!isset($_SESSION['soapobjects'][$name])) {
        $client = new SoapClient($wsdl, array('trace' => 1));
            $_SESSION['soapobjects'][$name]=serialize($client);
        } else {
            $client = unserialize($_SESSION['soapobjects'][$name]);
        }
    return $client;
}

那肯定是the way PHP recommends to do it

...然后这样称呼它...

$client = soap_client('servicename',$wsdl);
$client->MethodName($parameters);

但是,它似乎不起作用。

第一次运行时,它可以工作(即创建对象并制作序列化副本,并且方法调用工作正常)。但是第二次运行它就失败了。

对象似乎可以正确地序列化和反序列化,但是当您尝试对反序列化的对象执行 SOAP 调用时,它会引发以下错误:

Fatal error: Uncaught SoapFault exception: [Client] Error finding "uri" property

很明显,反序列化的对象与原始对象不同,这与对象序列化的工作方式不一致。

谁能解释我为什么会收到这个错误?您能否建议一种让它发挥作用的方法,或者我可以说服的替代策略?

谢谢。

ps - 我已经尝试解决这个问题,但没有任何乐趣。

我尝试在 options 参数中指定 URI(在 PHP SOAP Client manual 中指定),但没有任何区别。但无论如何都没有必要,因为我使用的是 WSDL。

我也尝试过简单地将对象复制到$_SESSION,而不使用serialize()deserialize(),但效果完全相同。

【问题讨论】:

    标签: serialization soap soap-client php


    【解决方案1】:

    内置的 SOAP 扩展是一个不可调试的可怕二进制块。它很可能在构建时没有考虑到序列化。例如,它可能包含在序列化/反序列化过程中无法生存的内部文件句柄。我强烈建议您使用其他一些 SOAP 客户端,例如:

    • Zend_Soap,Zend 框架的一部分。您不需要在代码的任何其他区域使用框架,并且可能可以删除大多数其他组件。但是,它似乎在幕后使用了现有的 SOAP 扩展,因此它可能不是一个很好的序列化候选者。
    • PEAR's SOAP 经常被引用,虽然它有点老了。
    • NuSOAP 最近已起死回生,但所有在线文档似乎都已消失在 zip 文件中。

    如果这些都不合适,请考虑在本地缓存 WSDL 文件,因为我以某种方式预计会出现延迟。

    【讨论】:

    • 感谢您的回复。我做了一些进一步的调查,看起来你的分析是正确的——序列化的字符串对于重建对象几乎没有用;它几乎没有任何内容,因此反序列化它不起作用也就不足为奇了。我会研究替代方案,但是 PHP SOAP 已经很好地融入了我们的应用程序,所以切换起来可能会很痛苦。我们已经研究过 WSDL 缓存;到目前为止它还没有奏效,但我会重新访问它,因为我认为我们之前没有做到这一点。
    • 我建议不要学习另一个soap扩展,而是研究wsdl缓存。除非当然有你追求的特定功能。
    • @Charles 使用 Zend_Soap_Client 也不起作用,因为它包装了一个 extended SoapClient 类。除非您以前没有使用过客户端,否则将其存储到 (Zend_) 缓存或 (Zend_) 会话中也会导致反序列化问题。由于 Zend_Soap_Client 延迟加载底层 SoapClient,这可能会导致应用程序中出现不可预见的副作用。
    • 谢谢@Partyschaum,我已将这些信息整合到我的答案中。
    【解决方案2】:

    根据您对上一个答案的 cmets,最好的选择是按照之前的建议将 Zend 框架仅用于soap,这将允许您继续使用 php,并且仍然可以使用 zend 获得更好的功能。如果您的需求增加,您也可以使用 Zend 的其他功能。

    这个例子可能会对你有所帮助 http://blog.fedecarg.com/2009/02/15/building-a-web-service-client-using-the-zend-framework/

    【讨论】:

      猜你喜欢
      • 2012-04-15
      • 2018-01-09
      • 1970-01-01
      • 1970-01-01
      • 2015-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-12
      相关资源
      最近更新 更多