PHP 7不一致地抛出错误

时间:2016-12-08 21:08:11

标签: php error-handling php-7

我目前正在尝试理解PHP 7中新错误处理的行为。

DivisionByZeroError的PHP文档中,它声明:

  

尝试分割a时抛出DivisionByZeroError   数字为零。

足够公平,但在使用/运算符时它不会抛出DivisionByZeroError。

在这个例子中,我希望能捕获到两个错误:

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";
}

而只是抓住了第一个:

  

抓住了DivisionByZeroError!

     

PHP警告:在第9行的TypeError.php中除以零...

为什么呢?还有其他这样的情况吗?我的理解是,如果你捕获Throwable,你将捕获任何可以引发的东西,这将使PHP错误处理更易于管理。但在这种情况下,如果我使用/运算符,那就是无法捕获的PHP警告。

这是否特定于此错误(可能是因为它是由操作员触发的),还是我误解了错误处理的变化?

2 个答案:

答案 0 :(得分:1)

使用算术运算符/不会在php 7中引发异常,而在php 8中会引发异常。

<?php

try {
    echo intdiv(2, 0);
} catch (DivisionByZeroError $e) {
    echo "caught division by zero for intdiv()\n";
}

try {
    echo (2 / 0);
} catch (DivisionByZeroError $e) {
    echo "caught division by zero for /\n";
}
# php 7
$ php test.php
caught division by zero for intdiv()
PHP Warning:  Division by zero in test.php on line 10
PHP Stack trace:
PHP   1. {main}() test.php:0

Warning: Division by zero in test.php on line 10

Call Stack:
    0.0740     417272   1. {main}() test.php:0

# php 8
$ php test.php

caught division by zero for intdiv()
caught division by zero for /

答案 1 :(得分:0)

我不认为这样做是为了向后兼容。相反,我觉得它是通过这种方式实现的,以便与其他语言保持一致:除法运算符符合浮点除法的IEEE-754 definitioncircumstance在一个且只有一个的情况下将执行整数除法,等效于intdiv

  

除法运算符(“ /”)会返回浮点值,除非两个操作数是整数(或转换为整数的字符串)并且数字可以被整除,在这种情况下,将返回整数值。有关整数除法,请参见intdiv()。

重要的是,并且仅在执行 integer 除法时,DivisionByZeroError doc中没有提到它。如果开发人员打算进行整数除法,则需要使用intdiv%。否则,开发人员仍必须检查股息是否接近零,并进行相应处理(所有其他浮点操作都是这种情况)。

从这个问题尚不清楚Throwable发生了什么问题,但是Throwable确实抓住了DivisionByZeroError

try {                                                                            
    intdiv(2, 0);                                                                
} catch (\Throwable $t) {                                                        
    echo 'caught' . PHP_EOL;                                                     
}                                                                                

但是,它不会被警告警告除以零,恰恰是因为这是一个警告,而不是例外。