PHP SOAP错误捕获

时间:2011-08-05 07:21:12

标签: php soap

我变得绝望,我想要的只是简单的错误处理,当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";
}
?>

7 个答案:

答案 0 :(得分:27)

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可能会导致致命错误。

首先,您需要打开异常处理:

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

然后您将找到它,而不是使用正确的消息“Soap错误:SOAP-ERROR:解析WSDL:无法从'...'加载”来跳过SoapFault异常,因此您最终返回到catch语句中能够更有效地处理错误。

答案 1 :(得分:19)

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. */

答案 2 :(得分:7)

不幸的是,当服务关闭/无法访问而不是返回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';
}

答案 3 :(得分:2)

也许是更好的选择:

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

您可以在上述功能中调整错误消息。 我用它来回复你所做同样情况的信息,因为它可以随时发生。

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

答案 4 :(得分:1)

我最终是这样处理的:

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

检查后再打个电话。

答案 5 :(得分:0)

事实证明一切都很简单-使用名称空间时,请确保指定根ns! 那些< script language = "javascript" type = "text/javascript" > function iFrameHeight() { var h = 0; if (!document.all) { h = document.getElementById('blockrandom').contentDocument.height; document.getElementById('blockrandom').style.height = h + 60 + 'px'; } else if (document.all) { h = document.frames('blockrandom').document.body.scrollHeight; } } < /script> < div > Tesseramento al Torneo Campioni di Amicizia < /div> < iframe onload = "iFrameHeight()" id = "blockrandom" name = "iframe" src = "https://app.softwaretessere.it/index.aspx" width = "300%" height = "1000" scrolling = "no" align = "top" frameborder = "0" > Questa scelta non funziona correttamente in quanto il browser utilizzato non supporta gli Inline Frames < /iframe> -错误,正确的方法catch (SoapFailt $fault)

答案 6 :(得分:-8)

SoapFault不会扩展Exception,捕获特定类型的工作:

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