php 异常处理

tech2023-12-03  30

php 异常处理

Errors are the most common event a developer faces when programming. Errors can be categorized as syntactical, run-time, or logical: missing the semicolon at the end of a statement is an example of a syntax error; trying to connect to a database when the server is down is an example of a run-time error; providing incorrect data to a variable is an example of a logic error. To help reduce the number of errors in your code, and to mitigate their effects, proper error handling is essential in your web application.

错误是开发人员在编程时面临的最常见事件。 错误可以归类为语法错误,运行时错误或逻辑错误:语句末尾缺少分号是语法错误的一个示例。 服务器关闭时尝试连接数据库是运行时错误的一个示例; 向变量提供不正确的数据是逻辑错误的一个示例。 为了帮助减少代码中的错误数量并减轻其影响,正确的错误处理对于Web应用程序至关重要。

This article is a crash course in PHP error handling. You’ll learn about PHP’s built-in error reporting levels, and how to handle errors with custom error handlers and exception handling.

本文是PHP错误处理的速成课程。 您将了解PHP的内置错误报告级别,以及如何使用自定义错误处理程序和异常处理来处理错误。

PHP错误报告级别 (PHP Error Reporting Levels)

All errors and warnings should be logged. Based on the severity of an error, notifications should be sent out to other systems/teams. So that you can better gauge its severity, PHP provides several built-in error levels to describe the nature of an error. Each level is represented by an integer value and named constant which can be used by the programmer. The table below is taken from the official PHP documentation and shows some of the different levels.

所有错误和警告均应记录。 根据错误的严重程度,应将通知发送到其他系统/团队。 为了更好地评估其严重性,PHP提供了一些内置的错误级别来描述错误的性质。 每个级别都由一个整数值和一个称为常量的常量表示,程序员可以使用它。 下表摘自PHP官方文档,并显示了一些不同的级别。

The levels can be masked together with bit-operators to include or subtract them from PHP’s configuration. For example, E_ALL|E_STRICT enables all errors and warnings with the addition of E_STRICT (necessary in versions of PHP prior to 5.4).

这些级别可以与位运算符一起屏蔽,以在PHP的配置中包括或减去它们。 例如, E_ALL|E_STRICT通过添加E_STRICT (在5.4之前PHP版本中是必需的)来启用所有错误和警告。

PHP provides a few configuration directives related to logging and displaying errors. Their values are generally different depending on whether the system is in a development or a production environment. This table shows some of the error-related directives.

PHP提供了一些与记录和显示错误有关的配置指令。 根据系统是处于开发环境还是生产环境,它们的值通常会有所不同。 下表显示了一些与错误相关的指令。

The configuration directives can be set either in php.ini, in a web server configuration file (httpd.conf or .htaccess file), or at run-time in your script using the ini_set() function. Read the documentation for more information on the directives and how/where to set them.

可以在php.ini ,Web服务器配置文件( httpd.conf或.htaccess文件)中设置配置指令,也可以在运行时使用ini_set()函数在脚本中设置配置指令。 阅读文档以获取有关指令以及如何/在何处设置它们的更多信息。

创建自定义错误处理程序 (Creating Custom Error Handlers)

It’s also good practice not to display raw errors to the end user. Errors that are displayed should be abstracted with friendly, custom error messages. PHP not only provides built-in functions for logging and displaying errors, but also for raising them. You can pragmatically trigger an error of a specific level using trigger_error(). For example, this code triggers an E_USER_NOTICE warning if the value of $test is greater than 1:

最好不要向最终用户显示原始错误。 显示的错误应使用友好的自定义错误消息进行抽象。 PHP不仅提供了用于记录和显示错误的内置函数,还提供了引发它们的功能。 您可以使用trigger_error()实用地触发特定级别的错误。 例如,如果$test的值大于1,则此代码触发E_USER_NOTICE警告。

<?php $test = 5; if ($test > 1) { trigger_error('Value of $test must be 1 or less', E_USER_NOTICE); }

Triggering errors with trigger_error() is useful when you have an error-handling infrastructure in place, allowing you to unify the handling of both custom errors and the errors and warnings raised by PHP.

当您具有适当的错误处理基础结构时,使用trigger_error()触发错误非常有用,它使您可以统一处理自定义错误以及PHP引发的错误和警告。

If you want to implement customized error handling strategies like sending an email or logging errors to a database based on their severity, then you’ll need to define custom error handlers using set_error_handler(). The function accepts two arguments: a callback function or static method that will be invoked when the error is raised, and optionally the error level the function/method handles. The signature of the callback is:

如果要实现自定义的错误处理策略,例如根据严重性发送电子邮件或将错误记录到数据库,则需要using set_error_handler()定义自定义错误处理程序。 该函数接受两个参数:引发错误时将调用的回调函数或静态方法,以及函数/方法处理的错误级别(可选)。 回调的签名是:

handler(int $errno, string $errstr, string $errfile, int $errline, array $errcontext)

Let’s take a look at a custom error handler function. The example below records errors to a database table database whenever one is encountered:

让我们看一下自定义错误处理函数。 下面的示例在遇到错误时将错误记录到数据库表数据库中:

<?php function errorHandler($errno, $errstr, $errfile, $errline) {     static $db;     if (empty($db)) {         $db = new PDO(DSN, DBUSER, DBPASS);    }     $query = "INSERT INTO errorlog (severity, message, filename, lineno, time) VALUES (?, ?, ?, ?, NOW())";    $stmt = $db->prepare($query);     switch ($errno) {         case E_NOTICE:         case E_USER_NOTICE:         case E_DEPRECATED:         case E_USER_DEPRECATED:         case E_STRICT:             $stmt->execute(array("NOTICE", $errstr, $errfile, $errline));             break;        case E_WARNING:         case E_USER_WARNING:             $stmt->execute(array("WARNING", $errstr, $errfile, $errline));             break;         case E_ERROR:         case E_USER_ERROR:             $stmt->execute(array("FATAL", $errstr, $errfile, $errline));             exit("FATAL error $errstr at $errfile:$errline");        default:             exit("Unknown error at $errfile:$errline");     } } set_error_handler("errorHandler"); $test = 5; if ($test > 1) {    trigger_error("Value of $test must be 1 or less", E_USER_NOTICE); }

The above snippet registers an error handler that does the following: when non-fatal errors occur, a record will be inserted into database instead of displaying the error and logging it to a file; When a fatal error occurs, it will be logged in database and terminate your script.

上面的代码片段注册了一个执行以下操作的错误处理程序:当发生非致命错误时,将一条记录插入数据库,而不是显示错误并将其记录到文件中; 发生致命错误时,它将记录在数据库中并终止您的脚本。

There are some limitations to custom error handlers you should be aware of, however. The error handler bypasses PHP’s standard error handling behavior, so it can’t handle errors that may arise within your handler itself. In the event the database server is down, for example, the above function would fail to record the log. Also, the error handler is not able to catch certain internal errors, like E_CORE_ERROR and E_COMPILE_ERROR, or E_STRICT errors in the same file the handler is defined in since those errors occur before the handler has a chance to be registered.

但是,您应该了解自定义错误处理程序的一些限制。 错误处理程序会绕过PHP的标准错误处理行为,因此它无法处理可能在您的处理程序自身内部发生的错误。 例如,如果数据库服务器已关闭,则上述功能将无法记录日志。 另外,错误处理程序无法捕获某些内部错误,例如E_CORE_ERROR和E_COMPILE_ERROR或在定义该处理程序的同一文件中的E_STRICT错误,因为这些错误发生在该处理程序有机会被注册之前。

使用异常处理错误 (Handling Errors using Exceptions)

However good of an error handling framework you have in place, there will always be problems at run-time. Of course you don’t want these errors to show up in the user’s browser. This is where exception handling enters the picture. Exceptions allows you to handle errors and exceptional situations gracefully.

无论您使用的错误处理框架有多棒,运行时总会出现问题。 当然,您不希望这些错误出现在用户的浏览器中。 这是异常处理进入画面的地方。 异常使您可以优雅地处理错误和特殊情况。

Exceptions are represented in PHP by the class Excpetion (or any of its subclasses). They can be raised using throw and can be caught using a try/catch block. You can extend Exception to create custom exception types for trapping specific errors.

在PHP中,异常由类Excpetion (或其任何子类)表示。 可以使用throw它们,也可以使用try/catch块try/catch 。 您可以扩展Exception以创建用于捕获特定错误的自定义异常类型。

The code that may trigger an exception is placed within the try block, and the code to handle the exception is placed within the catch block. Consider the following snippet:

可能触发异常的代码位于try块中,用于处理异常的代码位于catch块中。 考虑以下代码段:

<?php try {    $data = $this->getDataFromService(); } catch (Exception $e) {    echo "Caught exception: " . $e->getMessage() . "n"; }

If an exception is thrown by the fictitious getDataFromService() method, it will be caught in the catch block and a message will be displayed. If getDataFromService() executes successfully then the flow will pass over the catch block and continue through the rest of the script. Any exceptions that are thrown and not caught will generate an E_FATAL error with the message “Uncaught Exception.”

如果虚构的getDataFromService()方法引发了异常,则该异常将被捕获在catch块中并显示一条消息。 如果getDataFromService()成功执行,则流程将越过catch块并继续执行脚本的其余部分。 引发但未捕获的任何异常都将生成E_FATAL error ,并显示消息“未捕获的异常”。

The Exception class offers six different methods to access information about what caused the problem, as shown in the table below.

Exception类提供了六种不同的方法来访问有关导致问题的原因的信息,如下表所示。

创建一个自定义异常处理程序 (Creating a Custom Exception Handler)

PHP will let you throw any object as if it were an exception, but as a rule of thumb the exception should extend PHP’s built-in Exception class. Based on the object’s type, you can handle the exceptions differently. Custom exception handling can perform suitable actions like logging error messages in file, providing exact details about the line on which the error occurred by examining the calling stack, etc.  Have a look at this example:

PHP将允许您将任何对象当作异常抛出,但是根据经验,异常应扩展PHP的内置Exception类。 根据对象的类型,可以对异常进行不同的处理。 自定义异常处理可以执行适当的操作,例如在文件中记录错误消息,通过检查调用堆栈等提供有关发生错误的行的确切详细信息,请看以下示例:

<?php class NameException extends Exception { } class EmailException extends Exception { } $name = ""; $email= ""; try {    if (empty($name)) {        throw new NameException();    }    elseif (empty($email)) {        throw new EmailException();    }    else {        echo "Name is " . $name . "<br>";        echo "Email is " . $email;    } } catch (NameException $n) {    echo "A name was not provided.";    error_log($n->getTraceAsString()); } catch (EmailException $e) {    echo "An email address was not provided.";    error_log($e->getTraceAsString()); }

The code above defines two new custom exception types, NameException and EmailException, which can be used to indicate different errors. Then within the try block, the code checks if values have been supplied for the variables $name and $email. If either is empty, then the appropriate exception is thrown using throw. The corresponding catch block is executed which handles the error.

上面的代码定义了两个新的自定义异常类型, NameException和EmailException ,可以用来指示不同的错误。 然后在try块中,代码检查是否已为变量$name和$email提供了值。 如果任何一个为空,则使用throw引发适当的异常。 执行相应的catch块来处理错误。

重新抛出异常 (Re-throwing Exceptions)

try/catch blocks can be nested. Sometimes you’ll want to catch an exception, look at some of its properties, and then throw it again to let a parent catch block handle it. This can often be useful to check an error condition and decide whether it should be fatal or not. This example code demonstrates re-throwing an exception:

try/catch块可以嵌套。 有时,您可能想捕获一个异常,查看其某些属性,然后再次抛出该异常,以使父catch块对其进行处理。 这通常对于检查错误情况并确定是否致命是很有用的。 此示例代码演示了重新引发异常:

<?php class FileExistException extends Exception { } class FileReadException extends Exception { } $filename = 'D:Exception.txt'; try {     try {         $text = file_get_contents($filename);         if ($text === false) {             throw new Exception();         }     }    catch (Exception $e) {         if (!file_exists($filename)) {             throw new FileExistException($filename . " does not exist.");         }         elseif (!is_readable($filename)) {             throw new FileReadException($filename . " is not readable.");         }         else {             throw new Exception("Unknown error accessing file.");         }    } } catch (FileExistException $fe) {     echo $fe->getMessage();     error_log($fe->getTraceAsString()); } catch (FileReadException $fr) {     echo $fr->getMessage();    error_log($fr->getTraceAsString()); }

未捕获的异常处理程序 (Uncaught Exception Handler)

Similar to how set_error_handler() allows you specify a function to handle run-time errors, the set_exception_handler() function allows you to handle exceptions that make it all the way up the call stack without being caught by any catch blocks. For example, if an exception makes it all the way up your stack, it would be a good idea to log it in a log file. You can create a callback function and register it  with set_exception_handler() as shown in the example below.

与set_error_handler()允许您指定处理运行时错误的函数类似, set_exception_handler()函数允许您处理使异常一直遍及调用堆栈的异常,而不会被任何catch块catch 。 例如,如果异常一直遍及整个堆栈,则最好将其记录在日志文件中。 您可以创建一个回调函数,并使用set_exception_handler()注册它,如下面的示例所示。

<?php set_exception_handler(function ($exception) {    $file = "var/log/exceptionLog.log";    file_put_contents($file, $exception->__toString(), FILE_APPEND); }); throw new Exception();

摘要 (Summary)

PHP offers variety of built-in functions for handling error conditions, including logging and displaying them. It also provides you the flexibility to customize your error handling strategies by registering error handlers and using exceptions. Errors are a fact of life, but hopefully the information I presented in this article will help you handle them more gracefully.

PHP提供了各种内置函数来处理错误情况,包括记录和显示错误情况。 它还通过注册错误处理程序和使用异常,为您提供了自定义错误处理策略的灵活性。 错误是生活中不可或缺的事实,但是希望我在本文中介绍的信息将帮助您更优雅地处理它们。

Image via Ilya Andriyanov / Shutterstock

图片来自Ilya Andriyanov / Shutterstock

翻译自: https://www.sitepoint.com/error-handling-in-php/

php 异常处理

最新回复(0)