130

I am trying to run this Example #1 from this page: http://php.net/manual/en/language.exceptions.php

<?php
function inverse($x) {
    if (!$x) {
        throw new Exception('Division by zero.');
    }
    return 1/$x;
}
try {
    echo inverse(5) . "\n";
    echo inverse(0) . "\n";
} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
}
// Continue execution
echo "Hello World\n";
?>

However instead of the desired output I get:

0.2
Fatal error: Uncaught exception 'Exception' with message 'Division by zero.' 
in xxx:
7 Stack trace: #0 xxx(14): inverse(0) #1 {main} thrown in xxx on line 7

The developer environment I am using is UniServer 3.5 with PHP 5.2.3

0

9 Answers 9

256

It's likely a namespace issue.

I had my exception in my namespace called A and the script was in a namespace called B. The problem was that I had A\MyException which equals (in PHP) \B\A\MyException (because my script is in the namespace called B!). All I had to do to fix it was to add a backslash to the exception name so it would look like this: \A\MyException.

Without the backslash Exception is specific to the namespace and won't be caught.

Sign up to request clarification or add additional context in comments.

Comments

81

Just try changing Exception to \Exception. Worked for me!

Using namespace should do the same thing. So simply put use \Exception; before your class declaration.

Comments

62

\Exception didn't work for me because it's not topmost in the Exception hierarchy. I had to replace it with \Throwable, which is.

So I did it like this

try {
   ...
} catch(\Throwable $e){
   ...
}

and it worked like a charm!

For more information: PHP Error hierarchy

Comments

21

Note: This answer is largely outdated and written out of confusion. Warnings and Notices indeed cannot be caught, and never were intended to be. But Exceptions of course can be caught, and starting from PHP 8.0 the code below begins printing 'Got it!', provided \Throwable is used in the catch block as suggested in other answers.

You can not use the typical try{} catch{} blocks in PHP as you could do in another language like C# (Csharp).

If you do this:

try{
    //division by zero
    $number = 5/0;
}
catch(Exception $ex){
    echo 'Got it!';
}

You will never see the 'Got it!' message. Why? It's just because PHP always needs an Exception to be "Thrown". You need to set your own error handler and throw an Exception with it.

See set_error_handler function: http://php.net/manual/es/function.set-error-handler.php

Comments

6

My initial though is you have a typo in the name of the exception you are catching/throwing, but if your code is exactly the same I'm not sure exactly what is going on.

Try the following modification of the original script, and paste your results. It will help diagnose your issue a bit better.

<?php

//set up exception handler to report what we didn't catch
function exception_handler($exception) {

    if($exception instanceof MyException) {
        echo "you didn't catch a myexception instance\n";

    } else if($exception instanceof Exception) {
        echo "you didn't catch a exception instance\n";

    } else {
        echo "uncaught exception of type: ".gettype($exception)."\n";
    }

    echo "Uncaught exception: " , $exception->getMessage(), "\n";
}

//install the handler
set_exception_handler('exception_handler');

class MyException extends Exception {
}

function inverse($x) {
    if (!$x) {
        throw new MyException('Division by zero.');
    }
    else return 1/$x;
}

try {
    echo inverse(5) . "\n";
    echo inverse(0) . "\n";
} catch (MyException $e) {
    echo 'Caught myexception: ',  $e->getMessage(), "\n";
} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
}

// Continue execution
echo 'Hello World';
?>

Comments

4

I had the same problem with following configurations,

PHP 5.2.14 (cli) (built: Aug 12 2010 17:32:30) Copyright (c) 1997-2010 The PHP Group Zend Engine v2.2.0, Copyright (c) 1998-2010 Zend Technologies with eAccelerator v0.9.5.1, Copyright (c) 2004-2006 eAccelerator, by eAccelerator

The solution is to either disable eAccelerator or update it. I tried both and both of the fixes worked. The bug is reported here https://eaccelerator.net/ticket/242 (NB. firefox complains about their SSL cert) .

Now I am running try catch properly with following configurations,

PHP 5.2.4 (cli) (built: Oct 16 2007 09:13:35) Copyright (c) 1997-2007 The PHP Group Zend Engine v2.2.0, Copyright (c) 1998-2007 Zend Technologies with eAccelerator v0.9.6.1, Copyright (c) 2004-2010 eAccelerator, by eAccelerator

Comments

4

in Xdebug there is a setting:

xdebug.show_exception_trace = 1

This will force php to output exceptions even in a try catch block. Turn this to 0

2 Comments

In my case I had to disable the xdebug module completely (changing xdebug.show_exception_trace was not enough).
Thank you for this reminder. I was thoroughly confused for awhile.
2

TLDR; make sure you have use Exception; on the top of both php files

Comments

-1

I had not require_once'd the file containing my Exception subclass in the file with the try/catch block.

Somehow (maybe due to composer's autoload) this didn't result in a 'cannot be resolved to a type' error. And somehow my exception was being created with the expected namespace (in yet another file without the require_once). But it wasn't caught. My directory structure does not match the namespaces so autoload might have loaded the correct class in the file with the try/catch but under a different namespace.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.