I am currently trying to understand the behavior of the new error handling in PHP 7.
In the PHP Documentation for DivisionByZeroError
, it states:
DivisionByZeroError is thrown when an attempt is made to divide a number by zero.
Fair enough, but it does not throw the DivisionByZeroError when the / operator is used.
In this example, I would expect both errors to be caught:
declare(strict_types=1);
function usesIntDiv(int $a, int $b) {
return intdiv($a,$b);
}
function divide(int $a, int $b) {
return $a / $b;
}
try {
echo usesIntDiv(2,0);
} catch (DivisionByZeroError $e) {
echo "Caught DivisionByZeroError!\n";
}
echo "\n";
try {
echo divide(2,0);
} catch (DivisionByZeroError $e) {
echo "Caught DivisionByZeroError!\n";
}
Instead only the first one is caught:
Caught DivisionByZeroError!
PHP Warning: Division by zero in TypeError.php on line 9...
Why? Are there other cases like this? My understanding is that if you catch Throwable
you will catch anything that can be raised, which would make PHP error handling a bit more manageable. But in this case, if I use the /
operator, it is the uncatchable PHP warning.
Is this specific to this error (and maybe because it was triggered by an operator), or am I misunderstanding the change in error handling?
NOTE: The Engine Warnings RFC has changed the behavior. PHP 8+ will now always throw an exception when dividing by zero. PHP 7- exhibits the behavior described below.
I don't think it's this way for backward compatibility. Rather, I feel it's implemented this way for consistency with other languages: the division operator conforms to the IEEE-754 definition of floating point division. In one, and only one, circumstance will it perform integer division, equivalent to intdiv
:
The division operator ("/") returns a float value unless the two operands are integers (or strings that get converted to integers) and the numbers are evenly divisible, in which case an integer value will be returned. For integer division, see intdiv().
Importantly, and sadly not mentioned on the DivisionByZeroError doc, is that it's raised only when performing integer division. If a developer intends to have integer division, intdiv
or %
is called for. Otherwise, developers must still check dividend for near-zero conditions and handle accordingly (as is the case for all other floating-point operations).
It's not clear from the question what issue with Throwable
occurs, but Throwable
does catch the DivisionByZeroError
:
try {
intdiv(2, 0);
} catch (\Throwable $t) {
echo 'caught' . PHP_EOL;
}
However, it won't catch the division by zero warning, precisely because it's a warning not an exception.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With