framework: SoapFault exception cannot be caught when using SoapClient in Laravel

try {
$client = new SoapClient("wsdl-url-here",array('trace' => 1,'exceptions'=> true));
} catch (SoapFault $fault){
echo $fault->faultstring;
}

In the example above, if I have invalid WSDL URL, I am supposed to get SoapFault exception since I set exceptions to true. However, Laravel catches this as FATAL exception and the application crashes. This code works as expected outside of Laravel.

About this issue

  • Original URL
  • State: closed
  • Created 10 years ago
  • Reactions: 1
  • Comments: 27 (7 by maintainers)

Most upvoted comments

Actually, the SoapFault is successfully caught. However, Laravel is handling the last error in its handleShutdown method. Therefore, clear the last error to avoid the fatal error exception:

try {
    return $this->client = new SoapClient($this->getWsdlUrl(), [
        'cache_wsdl' => WSDL_CACHE_NONE,
        'exceptions' => true
    ]);
} catch (SoapFault $exception) {
    Log::error($exception);

    error_clear_last(); // The solution.
}

Tested in Laravel 5.2.

EDIT: Still working in Laravel 5.7. Also, updated comment to use error_clear_last() introduced in PHP 7. For versions below PHP 7.0 replace error_clear_last() with:

set_error_handler('var_dump', 0); // Never called because of empty mask.
@trigger_error("");
restore_error_handler();

Set your error_reporting to not include E_ERROR.

I have tried that as well, it still crashed with FATAL exception.

The solution is to actually ask the Soap client to throw a SoapFault instead of reporting an E_ERROR.

When the Soap client reports an E_ERROR, there is nothing for you to catch.

To fix this initialise you SoapClient like this:

        $clientOptions = array(
            'exceptions' => true,
        );

        try {
            $client = new \SoapClient("foo.wsdl", $clientOptions);
        } catch (\SoapFault $e) {
            // Do what you need to do!;
        }

        try {
            $result = $client->__soapCall($method, $data);
        } catch (\SoapFault $e) {
            // Do what you need to do!;
        }

hi i have this problem and it is uncatchable i think.

set_error_handler('var_dump', 0); // Never called because of empty mask.
@trigger_error("");
restore_error_handler();

This is working solution, soap thow exception and error than can not be catch. In catch SoapFault on php 7 can do this:

error_clear_last();

Less code.

My workaround in App\Exceptions\Handler for console application:

    protected function shouldntReport(Exception $e)
    {
        if ($this->isSoapError($e)) {
            return true;
        }
        return parent::shouldntReport($e);
    }

    public function renderForConsole($output, Exception $e)
    {
        if ($this->isSoapError($e)) {
            return;
        }
        return parent::renderForConsole($output, $e);
    }

    private function isSoapError(Exception $e)
    {
        return strpos($e->getMessage(), 'SOAP-ERROR: Parsing WSDL:') !== false;
    }