PHP SOAP error catching

php soapclient
php soapclient methods
php 7 soap
php soapclient https
php soap server
php soap proxy
soap authentication php
php soapclient classmap

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!

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

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

UPDATE July 2018

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.

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

Original answer relevant for older PHP versions

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.

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:

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::SoapFault - Manual, This class is used to send SOAP fault responses from the PHP handler. Can be used during SOAP header handling to report an error in the response header. To use it, create a SoapClient object with the exceptions option set to zero or FALSE. In this case, the SOAP method will return a special SoapFault object which encapsulates the fault details (faultcode, faultstring, faultactor and faultdetails). If exceptions is not set then SOAP call will throw an exception on error.

Fatal error: SOAP-ERROR: Parsing WSDL Means 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

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

You can check if the WSDL is present like this

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

SoapFault - Manual, Represents a SOAP fault. Class synopsis ¶. SoapFault extends Exception {. /* Inherited properties */. Keep in mind that from PHP 5.2.6 SOAP Fault has an HTTP Status Code = 200 if User-agent is "Shockwave Flash", but when Flash object is integrated into HTML page SOAP Server receives User-agent = Broswer-agent and NOT "Shockwave Flash".

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

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

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

PHP SOAP error catching, UPDATE July 2018. If you don't care about getting the SoapFault details and just want to catch any errors coming from the SoapClient you can  However, that didn't work for me. What worked worked for me was disabling the SOAP cache. It appears to have been caching the wrong requests and after disabling I actually noticed my requests were executing faster. On a linux server you can find this in your /etc/php.ini file. Look for soap.wsdl_cache_enabled=1 and change it to soap.wsdl_cache

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).'

SoapClient manage error / exception, SoapClient manage error / exception · php soap error-handling wsdl. I'm using a soap service that is unavailable today. It's returning a 403  503 means the functions are working and you're getting a response from the remote server denying you. If you ever tried to cURL google results the same thing happens, because they can detect the user-agent used by file_get_contents and cURL and as a result block those user agents.

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.

SoapFault exception cannot be caught when using SoapClient in , php to fix the issue temporarily. App::fatal(function($exception) { //If SOAP Error is found, we don't want to FATALLY crash but catch it instead  Note that the SoapClient.__doRequest() method circumvents the throwing of SoapFault exceptions. Specifically, if you call the __doRequest() method and it fails, it would normally throw a SoapFault exception. However, the __doRequest() meth

PHP SoapClient() gives error 500 and cannot catch the error , Went to an error 500 in production server while using PHP SoapClient library to connect to some third-party API. The error was really strange,  This error occurs because some versions of PHP SOAP client do not send the user name and password that you pass as the options input parameter of the SoapClient constructor . Yu need to pass the credentials in the web service URL like this:

Handling Exceptions Using SOAP Faults, In general, a SOAP fault is analogous to an application exception. SOAP faults are generated by receivers to report business logic errors or unexpected conditions. When an exception is thrown, the code following it will not be executed, and PHP will try to find the matching "catch" block. If an exception is not caught, a fatal error will be issued with an "Uncaught Exception" message. Lets try to throw an exception without catching it:

A SOAP Client with Error Handling : SOAP Client « Network « PHP, A SOAP Client with Error Handling <?php ini_set('soap.wsdl_cache_enabled', '​Off'); $soap = new SoapClient('guid.wsdl'); try { echo $soap->getGuid('PHP_'); }  SoapFault is an exception thrown by PHP SoapClient class (http://php.net/manual/en/class.soapfault.php). I have tried adding backslash but that didn't help. What I have found is that the SOAP exception is thrown and I can catch it, however, Laravel still crashes with FATAL SOAP exception.

Comments
  • Honestly, any fatal error in the SOAP extension should be reported as a bug since there is no case in which your code should cause a fatal error. 404 WSDL should be a SoapFault as you expect.
  • 'exceptions' => true is the default (on my system, anyway).
  • I tried set_error_handler, ob_start or register_shutdown_function and nothing could catch this error actually (windows php 7) except the php_errors.log :-(
  • Thanks for the update! Can you give an example how to get the soapfault with a throwable? I need the faultcode and faultstring for further actions.
  • I haven't tried it but you probably need to use the original solution to get to the actual SoapFault returned. I recall the problem is that a native PHP function errors inside the SOAP logic that prevents the SoapFault from being thrown properly
  • Hey, tnks for the reply, i get a response based on the username and password i give it, but i need to put in an error display if the server is down, which it is (as i have disconnected my network connection).. and i get that fatal error.
  • I edited my answer you have to try if the url is valid. and the do the soap thing
  • Tnk u, look like what im looking for, it just does not work xD and unfortunately i dnt reli have any experience with PHP cURL
  • Hey, got it to work, its not 404, it gives 0 if the service cannot be accessed and 200 if it can. Tnk u very much for all ur help :)
  • I don't like this answer, purely because then when you make your SOAP request it may very well be down again since it's an entirely separate network connection.
  • It DOES extend Exception!