0

How can I use the error control operator (@) in constructors?

The constructor for \DateTime will both throw an exception and raise a warning if a wrong argument is passed, but I would rather be able to catch the exception and handle it, and not get the warning. For this reason I would like to silence the warning e.g. using @.

If I catch the exception, the warning is still raised. I could try using the @ operator (although I don't know if it also prevents the exception from being raised). But I cannot get the syntax for this use case.

PHP version under test is 7.0.22.

❯ php -a
Interactive shell

php > new DateTime("abc");
PHP Warning:  Uncaught Exception: DateTime::__construct(): Failed to parse time string (abc) at position 0 (a): The timezone could not be found in the database in php shell code:1
Stack trace:
#0 php shell code(1): DateTime->__construct('abc')
#1 {main}
  thrown in php shell code on line 1

Warning: Uncaught Exception: DateTime::__construct(): Failed to parse time string (abc) at position 0 (a): The timezone could not be found in the database in php shell code:1
Stack trace:
#0 php shell code(1): DateTime->__construct('abc')
#1 {main}
  thrown in php shell code on line 1

php > $a = @new DateTime("abc");
PHP Warning:  Uncaught Exception: DateTime::__construct(): Failed to parse time string (abc) at position 0 (a): The timezone could not be found in the database in php shell code:1
Stack trace:
#0 php shell code(1): DateTime->__construct('abc')
#1 {main}
  thrown in php shell code on line 1

Warning: Uncaught Exception: DateTime::__construct(): Failed to parse time string (abc) at position 0 (a): The timezone could not be found in the database in php shell code:1
Stack trace:
#0 php shell code(1): DateTime->__construct('abc')
#1 {main}
  thrown in php shell code on line 1

php > $a = @(new DateTime("abc"));
PHP Warning:  Uncaught Exception: DateTime::__construct(): Failed to parse time string (abc) at position 0 (a): The timezone could not be found in the database in php shell code:1
Stack trace:
#0 php shell code(1): DateTime->__construct('abc')
#1 {main}
  thrown in php shell code on line 1

Warning: Uncaught Exception: DateTime::__construct(): Failed to parse time string (abc) at position 0 (a): The timezone could not be found in the database in php shell code:1
Stack trace:
#0 php shell code(1): DateTime->__construct('abc')
#1 {main}
  thrown in php shell code on line 1
php > 

php > $a = new @DateTime("abc");
PHP Parse error:  syntax error, unexpected '@' in php shell code on line 1

Parse error: syntax error, unexpected '@' in php shell code on line 1
jleeothon
  • 2,907
  • 4
  • 19
  • 35

3 Answers3

2

Why not use try catch?

try {
    $dt = new DateTime("abc");
} catch(Exception $e) {
    // do wathever you want
}
Claudio
  • 5,078
  • 1
  • 22
  • 33
1

What you can do is to use a custom handler function with set_error_handler, so that you can "catch" the warning/error the way you want.

here is an example i made to test if a regular expression is valid with it, i simply use an empty function because i didn't need to do anything with the warning:

function filterRegularExpression($str) {
    set_error_handler(function() {}, E_WARNING);
    $isRegularExpression = preg_match($str, '') !== false;
    restore_error_handler();
    if($isRegularExpression){
        return $str;
    }
    return false;
}
Kaddath
  • 5,933
  • 1
  • 9
  • 23
1

You are misunderstanding what is producing the warning. The warning is produced by the global error handler, because you did not catch the exception and it bubbled up to the top to terminate the program (or, well, produce a warning on the interactive CLI). The clue is that the warning is prefixed by "Uncaught Exception". If you catch the exception, no warning is produced. The DateTime constructor does not produce a warning of its own.

deceze
  • 510,633
  • 85
  • 743
  • 889