Code前端首页关于Code前端联系我们

PHP7异常和错误处理机制Exception, Error, Throwable

terry 2年前 (2023-09-25) 阅读数 49 #后端开发

Exception, Error, Throwable

PHP Exception, Error, Throwable

  • PHP 来自中将代码本身的异常(通常是由环境或语法引起的**)是错误称为 Error,运行过程中出现的逻辑错误称为Exception
  • 错误,无法通过代码处理,而异常可以通过 try /catch 处理
  • PHP7 * *Throwable 接口现已推出。该接口由ErrorException实现。用户无法直接实现 Throwable 接口,只能通过继承 Exception​来实现该接口

PHP7 异常处理机制

以前都是处理 fatal PHP 中几乎不可能出现错误。致命错误不会调用 set_error_handler() 设置的处理程序,而只是停止脚本运行。

在 PHP7 中,当发生致命错误和可捕获错误(E_ERRORE_RECOVERABLE_ERROR)时,会抛出异常,而不是立即停止脚本。在某些情况下,例如内存溢出,致命错误仍然会立即停止脚本执行,就像以前一样。在 PHP7 中,未捕获的异常也是致命错误。这意味着在 PHP5.x 中作为致命错误抛出的异常不会被捕获,并且在 PHP7 中也是致命错误。

注意:其他级别的错误如警告通知不会像以前那样抛出异常,只有致命恢复条 水平错误会破例的。

致命可恢复级别错误引发的异常不会从Exception类继承。这种分离是为了防止现有的 PHP5.x 代码用于防止脚本也捕获错误抛出的异常。由 fatalrecoverable 级别错误引起的异常是新分离的类 Error 的实例。与其他异常一样,Error类异常也可以被捕获和处理,并且也可以在块结构中运行,例如finally

Throwable

为了统一两个异常分支,ExceptionError都实现了一个新接口:Throwable

PH P7中新的异常结构如下:

interface Throwable
    |- Exception implements Throwable
        |- ...
    |- Error implements Throwable
        |- TypeError extends Error
        |- ParseError extends Error
        |- ArithmeticError extends Error
            |- DivisionByZeroError extends ArithmeticError
        |- AssertionError extends Error

如果类Throwable是在PHP7代码中定义的,它将如下所示:

interface Throwable
{
    public function getMessage(): string;
    public function getCode(): int;
    public function getFile(): string;
    public function getLine(): int;
    public function getTrace(): array;
    public function getTraceAsString(): string;
    public function getPrevious(): Throwable;
    public function __toString(): string;
}

这个界面看起来很熟悉。 Throwable指定的方法与Exception几乎相同。唯一的区别是 Throwable::getPrevious() 返回 Throwable 的实例,而不是 ExceptionExceptionError的构造函数与之前的Exception相同,可以接受任何Throwable的副本。

Throwable 可在 try/catch 块中使用,以删除 ExceptionError- 对象(或是未来可能的异常类型) 。请记住,最好识别更具体的异常类型并进行相应的处理。然而,在某些情况下我们想要捕获任何类型的异常(例如框架中的日志记录或错误处理)。 要捕获所有内容,在 PHP7 中,您应该使用 Throwable 而不是 Exception

try {
// Code that may throw an Exception or Error.
} catch (Throwable $t) {
// Handle exception
}

用户定义的类无法实现Throwable接口。做出此决定的部分原因是为了可预测性和一致性:只能抛出 ExceptionError 对象。此外,异常必须包含有关在回溯堆栈中创建对象的位置的信息,并且用户定义的对象不会自动具有用于存储此信息的参数。可以采用

Throwable来创建特定于包的接口或添加其他方法。从 Throwable 继承的接口只能通过子类化 ExceptionError 来实现。事实上,PHP5.X 中的所有错误都是FatalRecoverable 中的错误。 示例。与任何其他异常一样,可以使用 try/catch 块捕获Error 对象。

$var = 1;
try {
$var->method(); // Throws an Error object in PHP 7.
} catch (Error $e) {
// Handle error
}

通常,以前的致命错误会抛出基类实例Error,但有些错误会抛出更具体的Error子类:TypeError ParseErrorAssertionError

TypeError

当函数参数或返回值与声明的类型不匹配时,会抛出 TypeError 的实例。

function add(int $left, int $right)
{
return $left + $right;
}

try {
$value = add('left', 'right');
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}

//Argument 1 passed to add() must be of the type integer, string given

ParseError

如果文件中存在语法错误include/requireeval()代码,ParseError 被抛出。

try {
require 'file-with-parse-error.php';
} catch (ParseError $e) {
echo $e->getMessage(), "\n";
}

算术错误

算术错误在两种情况下产生。其中之一是搬迁操作的负面影响。第二个是在分子为PHP_INT_MIN时调用Intdiv()(),分母为-1(使用dission operator的此表达式:PHP_INT_MIN /-1,结果是浮点类型)。

try {
$value = 1 << -1;
catch (ArithmeticError $e) {
echo $e->getMessage();//Bit shift by negative number
}

Zererror除法

intdiv()的分母为或模运算(%)中的分母为0时,除法为Zererror抛出。请注意,在除法运算符 (/) 中使用 0 作为除数(即写为 xxx/0)只会触发警告。如果此时计数器不为零,则结果为 INF,如果计数器为 0,则结​​果为 NaN。

try {
$value = 1 % 0;
} catch (DivisionByZeroError $e) {
echo $e->getMessage();//Modulo by zero
}

AssertionError

如果不满足assert()的条件,则会抛出AssertionError

ini_set('zend.assertions', 1);
ini_set('assert.exception', 1);

$test = 1;

assert($test === 0);

//Fatal error: Uncaught AssertionError: assert($test === 0)

仅启用断言并设置 ini 配置 zend.assertions = 1assert.exception = 1assert() 被执行并且抛出 断言错误

使用Error

用户可以利用Error创建符合自己级别要求的Error类。这就提出了一个问题:什么情况下应该滚动Exception,什么情况下应该滚动Error

错误应用于指示需要程序员注意的代码问题。 PHP 引擎抛出的Error 对象属于这些类别,通常是代码级错误,例如将错误类型的参数传递给函数或解析文件时发生错误。当可以在运行时安全处理并且可以执行某些其他操作时,应使用Exception。由于

Error 对象不应在运行时处理,因此捕获 Error 对象也应该很少发生。一般来说,记录Error对象仅用于记录目的、执行必要的清理以及向用户显示错误消息。

编写代码以支持 PHP5 中的异常。

,然后异常。什么时候支持PHP5。

try {
// Code that may throw an Exception or Error.
} catch (Throwable $t) {
// Executed only in PHP 7, will not match in PHP 5.x
} catch (Exception $e) {
// Executed only in PHP 5.x, will not be reached in PHP 7
}

不幸的是,处理异常的函数中的类型声明不容易确定。当 Exception 用于函数参数类型声明并且调用函数时可以使用 Error 的实例时,该类型声明将被删除。如果不需要支持 PHP5.x,可以将类型声明重置为Throwable

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门