PHP 基础教程
PHP 高级教程
PHP & MySQL DATABASE
PHP 示例
PHP 参考手册

PHP 错误处理

在本教程中,您将学习如何使用 PHP 的错误处理函数来优雅地处理错误情况。

处理错误

有时您的应用程序不会按预期运行,从而导致错误。可能导致错误的原因有很多,例如:

  • Web 服务器可能磁盘空间不足
  • 用户可能在表单字段中输入了无效值
  • 您尝试访问的文件或数据库记录可能不存在
  • 应用程序可能无权写入磁盘上的文件
  • 应用程序需要访问的服务可能暂时不可用

这些类型的错误称为运行时错误,因为它们发生在脚本运行时。它们与脚本运行前需要修复的语法错误不同。

专业的应用程序必须具备优雅处理此类运行时错误的能力。通常这意味着更清楚、更准确地告知用户问题。

了解错误级别

通常,当出现阻止脚本正常运行的问题时,PHP 引擎会触发错误。每个错误都由一个整数值和一个相关的常数表示。下表列出了一些常见的错误级别:

错误级别 说明
E_ERROR 1 致命的运行时错误,无法从中恢复。 脚本的执行立即停止。
E_WARNING 2 运行时警告。 它不是致命的,大多数错误都属于这一类。 脚本的执行不会停止。
E_NOTICE 8 运行时通知。 表示脚本遇到了可能出错的情况,虽然正常运行脚本时也可能出现这种情况。
E_USER_ERROR 256 用户生成的致命错误消息。 这类似于 E_ERROR,除了它是由 PHP 脚本使用函数 trigger_error() 而不是 PHP 引擎生成的。
E_USER_WARNING 512 非致命的用户生成的警告消息。 这类似于 E_WARNING,只是它是由 PHP 脚本使用函数 trigger_error() 而不是 PHP 生成的。 引擎
E_USER_NOTICE 1024 用户生成的通知消息。 这就像一个 E_NOTICE,除了它是由 PHP 脚本使用函数 trigger_error() 而不是 PHP 引擎生成的。
E_STRICT 2048 严格来说不是错误,而是在 PHP 遇到可能导致问题或向前不兼容的代码时触发
E_ALL 8191 所有错误和警告,除了 PHP 5.4.0 之前的 E_STRICT

有关更多错误级别,请查看 PHP 错误级别上的参考。

PHP 引擎在遇到脚本问题时会触发错误,但您也可以自己触发错误以生成对用户更友好的错误消息。 通过这种方式,您可以使您的应用程序更加复杂。 以下部分描述了一些用于处理 PHP 中的错误的常用方法:

使用 die() 函数的基本错误处理

考虑以下示例,该示例仅尝试打开一个文本文件以进行只读。

示例

Download
<?php
// 尝试打开一个不存在的文件
$file = fopen("sample.txt", "r");
?>

如果该文件不存在,您可能会收到如下错误:

Warning: fopen(sample.txt) [function.fopen]: failed to open stream: No such file or directory in C:\wamp\www\project\test.asp on line 2

如果我们遵循一些简单的步骤,我们可以防止用户收到此类错误消息。

示例

Download
<?php
if(file_exists("sample.txt")){
    $file = fopen("sample.txt", "r");
} else{
    die("Error: The file you are trying to access doesn't exist.");
}
?>

现在,如果您运行上述脚本,您将收到如下错误消息:

Error: The file you are trying to access doesn't exist.

正如您所看到的,通过在尝试访问文件之前执行一个简单的检查文件是否存在,我们可以生成对用户更有意义的错误消息。

上面使用的 die() 函数只是显示自定义错误消息并在未找到"sample.txt"文件时终止当前脚本。


创建自定义错误处理程序

您可以创建自己的错误处理函数来处理 PHP 引擎生成的运行时错误。 自定义错误处理程序为您提供更大的灵活性并更好地控制错误,它可以检查错误并决定如何处理错误,它可能会向用户显示消息,将错误记录在文件或数据库中或通过 e 发送 -mail,尝试解决问题并继续,退出脚本的执行或完全忽略错误。

自定义错误处理函数必须能够处理至少两个参数(errno 和 errstr),但是它可以选择接受额外的三个参数(errfile、errline 和 errcontext),如下所述:

参数 说明
Required — 以下参数是必需的
errno 以整数形式指定错误级别。 这对应于适当的错误级别常量(E_ERRORE_WARNING 等)
errstr 将错误消息指定为字符串
Optional — The following parameters are optional
errfile 指定发生错误的脚本文件的文件名,作为字符串
errline 以字符串形式指定发生错误的行号
errcontext 指定一个数组,其中包含发生错误时存在的所有变量及其值。 对调试很有用

这是一个简单的自定义错误处理函数的示例。 这个处理程序,customError() 会在发生错误时触发,无论多么微不足道。 然后它将错误的详细信息输出到浏览器并停止脚本的执行。

示例

Download
<?php
// 错误处理函数
function customError($errno, $errstr){
    echo "<b>Error:</b> [$errno] $errstr";
}
?>

您需要告诉 PHP 使用您的自定义错误处理函数 — 只需调用内置的 set_error_handler() 函数,传入函数的名称。

示例

Download
<?php
// 错误处理函数
function customError($errno, $errstr){
    echo "<b>Error:</b> [$errno] $errstr";
}
 
// 设置错误处理程序
set_error_handler("customError");
 
// 触发错误
echo($test);
?>

错误记录

在文本文件中记录错误消息

您还可以将错误的详细信息记录到日志文件中,如下所示:

示例

Download
<?php
function calcDivision($dividend, $divisor){
    if($divisor == 0){
        trigger_error("calcDivision(): The divisor cannot be zero", E_USER_WARNING);
        return false;
    } else{
        return($dividend / $divisor);
    }
}
function customError($errno, $errstr, $errfile, $errline, $errcontext){
    $message = date("Y-m-d H:i:s - ");
    $message .= "Error: [" . $errno ."], " . "$errstr in $errfile on line $errline, ";
    $message .= "Variables:" . print_r($errcontext, true) . "\r\n";
    
    error_log($message, 3, "logs/app_errors.log");
    die("There was a problem, please try again.");
}
set_error_handler("customError");
echo calcDivision(10, 0);
echo "This will never be printed.";
?>

通过电子邮件发送错误消息

您还可以使用相同的 error_log() 函数发送包含错误详细信息的电子邮件。

示例

Download
<?php
function calcDivision($dividend, $divisor){
    if ($divisor == 0){
        trigger_error("calcDivision(): The divisor cannot be zero", E_USER_WARNING);
        return false;
    } else{
        return($dividend / $divisor);
    }
}
function customError($errno, $errstr, $errfile, $errline, $errcontext){
    $message = date("Y-m-d H:i:s - ");
    $message .= "Error: [" . $errno ."], " . "$errstr in $errfile on line $errline, ";
    $message .= "Variables:" . print_r($errcontext, true) . "\r\n";
    
    error_log($message, 1, "webmaster@example.com");
    die("There was a problem, please try again. Error report submitted to webmaster.");
}
set_error_handler("customError");
echo calcDivision(10, 0);
echo "This will never be printed.";
?>

触发错误

虽然 PHP 引擎在遇到脚本问题时会触发错误,但您也可以自己触发错误。 这有助于使您的应用程序更加健壮,因为它可以在潜在问题变成严重错误之前对其进行标记。

要从脚本中触发错误,请调用 trigger_error() 函数,并传入您要生成的错误消息:

trigger_error("There was a problem.");

考虑以下计算两个数字相除的函数。

示例

Download
<?php
function calcDivision($dividend, $divisor){
    return($dividend / $divisor);
}
 
// 调用函数
echo calcDivision(10, 0);
?>

如果将零 (0) 值作为 $divisor 参数传递,PHP 引擎生成的错误将如下所示:

Warning: Division by zero in C:\wamp\www\project\test.asp on line 3

这条消息看起来信息量不大。 考虑以下使用 trigger_error() 函数生成错误的示例。

示例

Download
<?php
function calcDivision($dividend, $divisor){
    if($divisor == 0){
        trigger_error("The divisor cannot be zero", E_USER_WARNING);
        return false;
    } else{
        return($dividend / $divisor);
    }
}
 
// 调用函数
echo calcDivision(10, 0);
?>

现在脚本生成此错误消息:

Warning: The divisor cannot be zero in C:\wamp\www\project\error.asp on line 4

如您所见,与前一个示例相比,第二个示例生成的错误消息更清楚地解释了问题。

Advertisements