87

I'm trying to do the following:

try {
    // just an example
    $time      = 'wrong datatype';
    $timestamp = date("Y-m-d H:i:s", $time);
} catch (Exception $e) {
    return false;
}
// database activity here

In short: I initialize some variables to be put in the database. If the initialization fails for whatever reason - e.g. because $time is not the expected format - I want the method to return false and not input wrong data into the database.

However, errors like this are not caught by the 'catch'-statement, but by the global error handler. And then the script continues.

Is there a way around this? I just thought it would be cleaner to do it like this instead of manually typechecking every variable, which seems ineffective considering that in 99% of all cases nothing bad happens.

Marcos
  • 1,117
  • 1
  • 8
  • 9
  • 3
    That's because exceptions are not universally implemented in PHP. They are a PHP5 addition, and very few of the built-in functions will throw them. Instead, you will need to verify the return values of most functions. – Michael Berkowski Mar 17 '13 at 14:07

5 Answers5

139
try {
  // call a success/error/progress handler
} catch (\Throwable $e) { // For PHP 7
  // handle $e
} catch (\Exception $e) { // For PHP 5
  // handle $e
}
Nabi K.A.Z.
  • 9,887
  • 6
  • 59
  • 81
  • 6
    Yes, this is heavily under-documented, you can barely notice it, if you're lucky and come to both https://www.php.net/manual/en/class.error.php and https://www.php.net/manual/en/class.exception.php links ... because the one that should contain this: https://www.php.net/manual/en/language.exceptions.php - *does not even contain word Throwable* (in doc part). – jave.web Sep 18 '19 at 13:21
  • In what circumstances would this go to the later catch block? When the Exception class implements the Throwable interface, wouldn't this always be catched in the first catch block? – Gemmu Jul 21 '21 at 09:51
  • @Gemmu [When the script runs with PHP 5](https://www.php.net/manual/en/class.throwable.php#124604) where `Throwable` does not exist. – AmigoJack Jan 26 '23 at 00:46
55

Solution #1

Use ErrorException to turn errors into exceptions to handle:

function exception_error_handler($errno, $errstr, $errfile, $errline ) {
    throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
}
set_error_handler("exception_error_handler");

Solution #2

try {
    // just an example
    $time      = 'wrong datatype';
    if (false === $timestamp = date("Y-m-d H:i:s", $time)) {
        throw new Exception('date error');
    }
} catch (Exception $e) {
    return false;
}
Federkun
  • 36,084
  • 8
  • 78
  • 90
  • 5
    A couple notes: 1) If it's not desired to universally raise exceptions in place of errors throughout the application, this can be enabled where desired and regular error handling can be restored with [`restore_error_handler()`](http://php.net/restore_error_handler). 2) I expect #2 to still throw a warning. Same concept applies: the error reporting level could be changed with [`error_reporting()`](http://www.php.net/manual/en/function.error-reporting.php) and changed back afterward. – Wiseguy Mar 17 '13 at 14:23
  • 2
    The warning MUST BE threw anyway. They are information that you must save it somewhere. If you do not want to see it, just turn off `error_display` – Federkun Mar 17 '13 at 14:27
  • 1
    Solution #2 is how Js does it... it's good if you know what you're doing – Ray Foss Feb 03 '18 at 19:51
  • 1
    Follow up question: Is it good idea to use solution #1 in your MVC applications? I feel using it globally defeats the purpose of Exceptions while repeatedly using `restore_error_handler()` feels very hackish. –  Mar 19 '18 at 12:50
  • 1
    Only on debug mode @VarunAgrawal, during the developement. I'd not relay on a global php setting to handle correctly how your application will in fact run in the end. – Federkun Mar 20 '18 at 20:50
  • 1
    @Federkun Thanks. That's actually quite a strong argument. I will stay away from these in future –  Mar 20 '18 at 22:22
  • For PHP 7 must catch \Throwable separately See the other answer. – ChrisDeDavidMindflowAU Aug 28 '20 at 17:14
12

The shorter that I have found:

set_error_handler(function($errno, $errstr, $errfile, $errline ){
    throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
});

Makes all errors becoming instance of catchable ErrorException

Luca C.
  • 11,714
  • 1
  • 86
  • 77
12

It is possible to use catch(Throwable $e) to catch all exceptions and errors like so:

catch ( Throwable $e){
    $msg = $e->getMessage();
}
Amal Magdy
  • 177
  • 1
  • 4
7

It's also possible to define multiple types for the $e parameter in catch:

try {
    // just an example
    $time      = 'wrong datatype';
    $timestamp = date("Y-m-d H:i:s", $time);
} catch (Exception|TypeError $e) {
    return false;
}
mikiqex
  • 5,023
  • 2
  • 24
  • 22