PHP SOAP 错误捕获

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6952814/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 01:40:17  来源:igfitidea点击:

PHP SOAP error catching

phpsoap

提问by David

I'm getting desperate, all I want is simple error handling when the PHP SOAP Web Service is down to echo an error message login service down. Please help me!

我越来越绝望,我想要的只是简单的错误处理,当 PHP SOAP Web 服务关闭以回显错误消息login service down 时。请帮我!

At the moment it's still displaying the error (along with warnings...):

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

Fatal error: SOAP-ERROR: Parsing WSDL

Fatal error: SOAP-ERROR: Parsing WSDL

Here is the script:

这是脚本:

<?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";
}
?>

回答by MeatPopsicle

UPDATE July 2018

2018 年 7 月更新

If you don't care about getting the SoapFault details and just want to catch any errors coming from the SoapClient you can catch "Throwable" in PHP 7+. The original problem was that SoapClient can "Fatal Error" before it throws a SoapFault so by catching both errors and exceptions with Throwable you will have very simple error handling e.g.

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

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

If you need to catch the SoapFault specifically, try the original answer which should allow you to suppress the fatal error that prevents the SoapFault being thrown

如果您需要专门捕获 SoapFault,请尝试原始答案,该答案应该允许您抑制防止抛出 SoapFault 的致命错误

Original answer relevant for older PHP versions

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

SOAP can fatal error calling the native php functions internally which prevents the SoapFaults being thrown so we need to log and suppress those native errors.

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

First you need to turn on exceptions handling:

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

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';
}

AND THEN you also need to silently suppress any "PHP errors" that originate from SOAP using a custom error handler:

然后,您还需要使用自定义错误处理程序静默抑制源自 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
    }
}

You will then find it now instead trips a SoapFault exception with the correct message "Soap error: SOAP-ERROR: Parsing WSDL: Couldn't load from '...'" and so you end up back in your catch statement able to handle the error more effectively.

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

回答by yokoloko

Fatal error: SOAP-ERROR: Parsing WSDLMeans the WSDL is wrong and maybe missing? so it's not related to soap. And you cannot handle FATAL ERROR with a try catch. See this link : http://ru2.php.net/set_error_handler#35622

Fatal error: SOAP-ERROR: Parsing WSDL意味着 WSDL 是错误的并且可能丢失了?所以它与肥皂无关。并且您无法使用 try catch 处理 FATAL ERROR。请参阅此链接:http: //ru2.php.net/set_error_handler#35622

What do you get when you try to access http://192.168.0.142:8080/services/Logon?wsdlin your browser?

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

You can check if the WSDL is present like this

您可以像这样检查 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. */

回答by Brad Kent

Unfortunately SOAP throws a fatal error when the service is down / unreachable rather than returning a SoapFault object.

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

That being said, you can set it to throw an exception. You probably omitted the part where you're setting the exceptions soap_client option to false

话虽如此,您可以将其设置为抛出异常。您可能省略了将异常 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
));

Catch the exception when service is down:

服务宕机时捕获异常:

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';
}

回答by Jonathan

Perhaps a better alternative:

也许更好的选择:

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);
}

Where you can adjust error messages in the mentioned functions. I use it to return a message in the same situation you do, as it can occur at any time.

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

Say you send a soap message after the initial login, and that response never arrives or arrives only partially, this way you can return a message without any script paths, names and linenumbers. In such cases I do not return $e at all, instead I just output something like: 'Something went wrong, please try it again (later).'

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

回答by Aurimas Rek?tys

I ended up handling it this way:

我最终以这种方式处理它:

       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);

Do your soap call after this check.

       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);

在此检查后进行肥皂呼叫。

回答by gsoft

Everything turned out to be much more trivial - when using namespaces, be sure to specify the root ns! Those catch (SoapFailt $fault)- is wrong, right way catch (\SoapFault $fault)

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

回答by Silvio Pereira Guedes

SoapFault doesn't extends Exception, catch the especific type works:

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';
}