【问题标题】:PHP SOAP error catchingPHP SOAP 错误捕获
【发布时间】:2011-08-05 07:21:12
【问题描述】:

我快绝望了,我想要的只是当 PHP SOAP Web 服务关闭时进行简单的错误处理以回显错误消息登录服务关闭。请帮帮我!

目前它仍在显示错误(以及警告...):

Fatal error: SOAP-ERROR: Parsing WSDL

这是脚本:

<?php
session_start(); 
$login="0000000000000nhfidsj"; //It is like this for testing, It will be changed to a GET

$username = substr($login,0,13); //as password is always 13 char long 
                                 //(the validation is done int he javascript)
$password = substr($login,13);
try 
{
    ini_set('default_socket_timeout', 5); //So time out is 5 seconds
    $client = new SoapClient("http://192.168.0.142:8080/services/Logon?wsdl"); //locally hosted

    $array = $client->login(array('username'=>$username,
                                   'password'=>$password));

    $result = $array->return;

}catch(SoapFault $client){
    $result = "0";
}

if($result == "true")//as this would be what the ws returns if login success 
{
    $_SESSION['user'] = $login;
    echo "00";
}
else
{
    echo "01 error: login failed";
}
?>

【问题讨论】:

  • 老实说,SOAP 扩展中的任何致命错误都应该报告为错误,因为您的代码不会导致致命错误。如您所料,404 WSDL 应该是 SoapFault。

标签: php soap


【解决方案1】:

2018 年 7 月更新

如果您不关心获取 SoapFault 详细信息而只想捕获来自 SoapClient 的任何错误,您可以在 PHP 7+ 中捕获“Throwable”。最初的问题是 SoapClient 在引发 SoapFault 之前可以“致命错误”,因此通过使用 Throwable 捕获错误和异常,您将获得非常简单的错误处理,例如

try{
    soap connection...
}catch(Throwable $e){
    echo 'sorry... our service is down';
}

如果您需要专门捕获 SoapFault,请尝试原始答案,这应该可以让您抑制阻止引发 SoapFault 的致命错误

与旧 PHP 版本相关的原始答案

SOAP 可能会在内部调用本机 php 函数发生致命错误,这会阻止引发 SoapFaults,因此我们需要记录并抑制这些本机错误。

首先你需要开启异常处理:

try {
    $client = new SoapClient("http://192.168.0.142:8080/services/Logon?wsdl",array(
       'exceptions' => true,
    ));
} catch ( SoapFault $e ) { // Do NOT try and catch "Exception" here
    echo 'sorry... our service is down';
}

然后您还需要使用自定义错误处理程序静默抑制源自 SOAP 的任何“PHP 错误”:

set_error_handler('handlePhpErrors');
function handlePhpErrors($errno, $errmsg, $filename, $linenum, $vars) {
    if (stristr($errmsg, "SoapClient::SoapClient")) {
         error_log($errmsg); // silently log error
         return; // skip error handling
    }
}

然后您会发现它现在会触发 SoapFault 异常并显示正确的消息“Soap 错误:SOAP-ERROR:解析 WSDL:无法从 '...' 加载”,因此您最终回到了 catch 语句能够更有效地处理错误。

【讨论】:

  • 'exceptions' =&gt; true 是默认值(无论如何,在我的系统上)。
  • 我尝试了 set_error_handler、ob_start 或 register_shutdown_function,除了 php_errors.log 之外,实际上没有任何东西可以捕捉到这个错误(windows php 7):-(
  • 感谢您的更新!你能举一个例子如何用一个可扔的东西来获得肥皂故障吗?我需要故障代码和故障字符串以进行进一步操作。
  • 我没有尝试过,但您可能需要使用原始解决方案才能获得实际返回的 SoapFault。我记得问题是 SOAP 逻辑中的本机 PHP 函数错误阻止了 SoapFault 被正确抛出
【解决方案2】:

Fatal error: SOAP-ERROR: Parsing WSDL 表示 WSDL 错误并且可能丢失?所以它与肥皂无关。而且你不能用 try catch 来处理 FATAL ERROR。见此链接:http://ru2.php.net/set_error_handler#35622

当您尝试在浏览器中访问http://192.168.0.142:8080/services/Logon?wsdl 时会得到什么?

您可以像这样检查 WSDL 是否存在

$handle = curl_init($url);
curl_setopt($handle,  CURLOPT_RETURNTRANSFER, TRUE);

$response = curl_exec($handle);
$httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE);
if($httpCode == 404) {
    /* You don't have a WSDL Service is down. exit the function */
}

curl_close($handle);

/* Do your stuff with SOAP here. */

【讨论】:

  • 嘿,tnks 回复,我根据我给它的用户名和密码得到一个响应,但是如果服务器关闭,我需要输入一个错误显示,它是(因为我已断开我的网络连接).. 我收到了致命错误。
  • 我编辑了我的答案,如果网址有效,您必须尝试。和做肥皂的事
  • Tnk u,看起来像我要找的东西,它只是不起作用 xD,不幸的是我没有任何使用 PHP cURL 的经验
  • 嘿,让它工作,它不是 404,如果服务无法访问,它给出 0,如果可以访问,它给出 200。非常感谢你的帮助:)
  • 我不喜欢这个答案,纯粹是因为当您发出 SOAP 请求时,它很可能会再次关闭,因为它是一个完全独立的网络连接。
【解决方案3】:

不幸的是,当服务关闭/无法访问而不是返回 SoapFault 对象时,SOAP 会引发致命错误。

话虽如此,您可以将其设置为抛出异常。您可能省略了将异常soap_client 选项设置为false 的部分

$client = new SoapClient("http://192.168.0.142:8080/services/Logon?wsdl",array(
    'exceptions' => false,    // change to true so it will throw an exception
));

在服务关闭时捕获异常:

try {
  $client = new SoapClient("http://192.168.0.142:8080/services/Logon?wsdl",array(
    'exceptions' => true,
  ));
}
catch ( Exception $e )
{
    echo 'sorry... our service is down';
}

【讨论】:

    【解决方案4】:

    也许是更好的选择:

    set_error_handler('my_error_handler');
    set_exception_handler('my_exception_handler');
    
    function my_exception_handler($e) {
        exit('Error, something went terribly wrong: '.$e);
    }
    
    function my_error_handler($no,$str,$file,$line) {
        $e = new ErrorException($str,$no,0,$file,$line);
        my_exception_handler($e);
    }
    

    您可以在哪里调整上述功能中的错误消息。 我使用它在与您相同的情况下返回消息,因为它可能随时发生。

    假设您在初始登录后发送了一条soap消息,并且该响应永远不会到达或仅部分到达,这样您就可以在没有任何脚本路径、名称和行号的情况下返回一条消息。 在这种情况下,我根本不返回 $e,而是输出如下内容:“出了点问题,请再试一次(稍后)。”

    【讨论】:

      【解决方案5】:

      我最终是这样处理的:

             libxml_use_internal_errors(true);
              $sxe = simplexml_load_string(file_get_contents($url));
              if (!$sxe) {
                  return [
                      'error' => true,
                      'info' => 'WSDL does not return valid xml',
                  ];
              }
              libxml_use_internal_errors(false);
      

      在检查后打电话。

      【讨论】:

        【解决方案6】:

        一切都变得更简单了——使用命名空间时,一定要指定根 ns! 那些catch (SoapFailt $fault) - 是错误的,正确的方式catch (<strong>\</strong>SoapFault $fault)

        【讨论】:

          【解决方案7】:

          SoapFault 不扩展异常,捕捉特定类型的工作:

          try {
            $client = new SoapClient("http://192.168.0.142:8080/services/Logon?wsdl",array(
              'exceptions' => true,
            ));
          }
          catch ( SoapFault $e )
          {
              echo 'sorry... our service is down';
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2018-04-19
            • 2018-03-29
            • 1970-01-01
            • 2011-01-20
            • 1970-01-01
            • 2013-05-07
            • 2015-10-15
            相关资源
            最近更新 更多