error_get_last() 是PHP内置的错误处理函数,用于获取最后发生的错误信息。它返回一个关联数组,包含最后一次错误的详细信息,包括错误类型、错误消息、发生错误的文件和行号。
error_get_last() 只返回脚本执行期间发生的最后一个错误。如果需要获取所有错误,需要使用自定义错误处理器。
array|null error_get_last(void)
该函数不需要任何参数,返回最后发生的错误的详细信息数组,如果没有发生错误则返回 null。
返回一个包含以下键的关联数组,如果没有错误发生则返回 null:
| 键名 | 描述 | 示例值 |
|---|---|---|
type |
错误类型(整数) | 2 (E_WARNING), 8 (E_NOTICE), 256 (E_USER_ERROR) 等 |
message |
错误消息 | "Undefined variable: undefinedVar" |
file |
发生错误的文件名 | "/var/www/html/test.php" |
line |
发生错误的行号 | 15 |
| 常量 | 值 | 描述 | 说明 |
|---|---|---|---|
E_ERROR |
1 | 致命运行时错误 | 脚本终止执行的错误 |
E_WARNING |
2 | 运行时警告 | 非致命错误,脚本继续执行 |
E_PARSE |
4 | 编译时解析错误 | 语法解析错误 |
E_NOTICE |
8 | 运行时通知 | 可能是错误也可能不是 |
E_CORE_ERROR |
16 | PHP初始化启动期间致命错误 | PHP引擎启动时的致命错误 |
E_USER_ERROR |
256 | 用户生成的错误 | 用户调用trigger_error()生成 |
E_USER_WARNING |
512 | 用户生成的警告 | 用户调用trigger_error()生成 |
E_USER_NOTICE |
1024 | 用户生成的通知 | 用户调用trigger_error()生成 |
E_STRICT |
2048 | 运行时通知 | PHP建议的代码修改 |
E_RECOVERABLE_ERROR |
4096 | 可捕获的致命错误 | 可被错误处理器捕获的致命错误 |
E_ALL |
32767 | 所有错误和警告 | PHP 5.4之前是30719,之后是32767 |
演示如何获取和处理最后一个错误:
<?php
// 触发一个警告
echo $undefinedVariable;
// 获取最后一个错误
$lastError = error_get_last();
echo "<h4>最后错误信息:</h4>";
if ($lastError) {
echo "<ul>";
echo "<li>类型: " . $lastError['type'] . " (" . getErrorTypeName($lastError['type']) . ")</li>";
echo "<li>消息: " . $lastError['message'] . "</li>";
echo "<li>文件: " . $lastError['file'] . "</li>";
echo "<li>行号: " . $lastError['line'] . "</li>";
echo "</ul>";
} else {
echo "没有错误发生";
}
// 辅助函数:将错误类型常量转换为可读名称
function getErrorTypeName($type) {
$errorTypes = [
1 => 'E_ERROR',
2 => 'E_WARNING',
4 => 'E_PARSE',
8 => 'E_NOTICE',
16 => 'E_CORE_ERROR',
32 => 'E_CORE_WARNING',
64 => 'E_COMPILE_ERROR',
128 => 'E_COMPILE_WARNING',
256 => 'E_USER_ERROR',
512 => 'E_USER_WARNING',
1024 => 'E_USER_NOTICE',
2048 => 'E_STRICT',
4096 => 'E_RECOVERABLE_ERROR',
8192 => 'E_DEPRECATED',
16384 => 'E_USER_DEPRECATED',
32767 => 'E_ALL'
];
return isset($errorTypes[$type]) ? $errorTypes[$type] : '未知类型';
}
结合set_error_handler()和error_get_last()处理错误:
<?php
// 自定义错误处理器
function customErrorHandler($errno, $errstr, $errfile, $errline) {
// 记录错误到日志
error_log("错误: [$errno] $errstr 在 $errfile 第 $errline 行");
// 显示友好的错误信息
echo "<div style='border: 1px solid #f00; background: #fee; padding: 10px; margin: 10px 0;'>";
echo "<strong>系统发生了一个错误:</strong><br>";
echo "错误信息: " . htmlspecialchars($errstr) . "<br>";
echo "位置: $errfile 第 $errline 行";
echo "</div>";
// 返回true表示已处理错误,阻止PHP默认错误处理器执行
return true;
}
// 设置自定义错误处理器
set_error_handler("customErrorHandler", E_ALL);
// 触发一些错误
echo $undefinedVar; // 未定义变量警告
file_get_contents("non_existent_file.txt"); // 文件不存在警告
strpos(); // 缺少参数警告
// 获取最后一个错误的详细信息
$lastError = error_get_last();
echo "<h4>最后错误的详细信息:</h4>";
if ($lastError) {
echo "<pre>" . print_r($lastError, true) . "</pre>";
}
// 恢复默认错误处理器
restore_error_handler();
在文件操作失败时获取错误信息:
<?php
function safeFileRead($filename) {
// 尝试读取文件
$content = @file_get_contents($filename);
if ($content === false) {
// 文件读取失败,获取错误信息
$error = error_get_last();
// 记录到错误日志
$errorMsg = isset($error['message']) ? $error['message'] : '未知错误';
error_log("文件读取失败: $filename - $errorMsg");
// 返回自定义错误信息
return [
'success' => false,
'error' => '无法读取文件: ' . htmlspecialchars($errorMsg),
'file' => $filename
];
}
return [
'success' => true,
'content' => $content
];
}
// 测试读取不存在的文件
$result = safeFileRead('non_existent_file.txt');
echo "<h4>文件读取结果:</h4>";
echo "<pre>" . print_r($result, true) . "</pre>";
// 获取最后一个错误
$lastError = error_get_last();
echo "<h4>最后错误:</h4>";
echo "<pre>" . print_r($lastError, true) . "</pre>";
在数据库操作中使用error_get_last()获取错误:
<?php
// 模拟数据库连接和查询
function executeQuery($sql) {
// 模拟数据库查询失败
if (strpos($sql, 'SELECT') !== false) {
// 故意触发错误
$result = false;
if (!$result) {
// 记录数据库错误
$errorInfo = [
'type' => 2, // E_WARNING
'message' => "Query failed: " . htmlspecialchars($sql),
'file' => __FILE__,
'line' => __LINE__
];
// 在实际应用中,这里可能会调用 error_log() 或记录到数据库错误日志
error_log("数据库查询失败: " . $errorInfo['message']);
return [
'success' => false,
'error' => $errorInfo['message']
];
}
}
return [
'success' => true,
'data' => ['id' => 1, 'name' => '测试用户']
];
}
// 执行查询
$query = "SELECT * FROM users WHERE id = 999";
$result = executeQuery($query);
echo "<h4>查询结果:</h4>";
if (!$result['success']) {
echo "<div style='color: red;'>错误: " . $result['error'] . "</div>";
// 获取并显示最后错误
$lastError = error_get_last();
if ($lastError) {
echo "<h4>系统最后错误:</h4>";
echo "<pre>" . print_r($lastError, true) . "</pre>";
}
} else {
echo "<pre>" . print_r($result['data'], true) . "</pre>";
}
在try-catch块中使用error_get_last():
<?php
// 设置自定义错误处理器
set_error_handler(function($errno, $errstr, $errfile, $errline) {
// 将错误转换为异常
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
});
try {
// 触发一些错误
echo $undefinedVariable;
} catch (ErrorException $e) {
echo "<div style='border: 1px solid #f00; padding: 10px; background: #fee;'>";
echo "<h4>捕获到异常:</h4>";
echo "消息: " . $e->getMessage() . "<br>";
echo "文件: " . $e->getFile() . "<br>";
echo "行号: " . $e->getLine() . "<br>";
echo "错误代码: " . $e->getCode() . "<br>";
echo "</div>";
// 使用 error_get_last() 获取错误信息
$lastError = error_get_last();
echo "<h4>通过 error_get_last() 获取:</h4>";
if ($lastError) {
echo "<ul>";
foreach ($lastError as $key => $value) {
echo "<li>$key: " . htmlspecialchars($value) . "</li>";
}
echo "</ul>";
}
} finally {
// 恢复错误处理器
restore_error_handler();
}
创建一个完整的错误日志记录器:
<?php
class ErrorLogger {
private $logFile;
private $errors = [];
public function __construct($logFile = 'error.log') {
$this->logFile = $logFile;
// 设置自定义错误处理器
set_error_handler([$this, 'handleError']);
// 设置自定义异常处理器
set_exception_handler([$this, 'handleException']);
// 设置关闭函数,在脚本结束时记录所有错误
register_shutdown_function([$this, 'shutdownHandler']);
}
public function handleError($errno, $errstr, $errfile, $errline) {
$error = [
'type' => $errno,
'message' => $errstr,
'file' => $errfile,
'line' => $errline,
'timestamp' => date('Y-m-d H:i:s'),
'backtrace' => debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5)
];
$this->errors[] = $error;
// 记录到文件
$this->logToFile($error);
// 不阻止PHP默认错误处理器
return false;
}
public function handleException($exception) {
$error = [
'type' => 'EXCEPTION',
'message' => $exception->getMessage(),
'file' => $exception->getFile(),
'line' => $exception->getLine(),
'timestamp' => date('Y-m-d H:i:s'),
'backtrace' => $exception->getTrace()
];
$this->errors[] = $error;
$this->logToFile($error);
}
public function shutdownHandler() {
// 获取最后的致命错误
$lastError = error_get_last();
if ($lastError && in_array($lastError['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) {
$fatalError = [
'type' => 'FATAL',
'message' => $lastError['message'],
'file' => $lastError['file'],
'line' => $lastError['line'],
'timestamp' => date('Y-m-d H:i:s')
];
$this->errors[] = $fatalError;
$this->logToFile($fatalError);
// 在脚本结束时显示致命错误
if (php_sapi_name() !== 'cli') {
echo "<div style='background: #fdd; border: 2px solid red; padding: 15px; margin: 10px;'>";
echo "<h3>致命错误</h3>";
echo "<p>消息: " . htmlspecialchars($lastError['message']) . "</p>";
echo "<p>位置: " . $lastError['file'] . " 第 " . $lastError['line'] . " 行</p>";
echo "</div>";
}
}
// 显示错误统计
if (count($this->errors) > 0) {
echo "<!-- 脚本执行期间发生了 " . count($this->errors) . " 个错误 -->";
}
}
private function logToFile($error) {
$logEntry = "[" . $error['timestamp'] . "] ";
$logEntry .= "[" . $this->getErrorTypeName($error['type']) . "] ";
$logEntry .= $error['message'] . " ";
$logEntry .= "in " . $error['file'] . ":" . $error['line'] . PHP_EOL;
file_put_contents($this->logFile, $logEntry, FILE_APPEND);
}
public function getErrors() {
return $this->errors;
}
public function getLastError() {
$lastError = error_get_last();
if ($lastError) {
$lastError['timestamp'] = date('Y-m-d H:i:s');
}
return $lastError;
}
private function getErrorTypeName($type) {
$errorTypes = [
1 => 'E_ERROR',
2 => 'E_WARNING',
4 => 'E_PARSE',
8 => 'E_NOTICE',
256 => 'E_USER_ERROR',
512 => 'E_USER_WARNING',
1024 => 'E_USER_NOTICE',
'EXCEPTION' => 'EXCEPTION',
'FATAL' => 'FATAL'
];
return isset($errorTypes[$type]) ? $errorTypes[$type] : 'UNKNOWN';
}
}
// 使用示例
$logger = new ErrorLogger('app_errors.log');
// 触发一些错误
echo $undefinedVar; // 触发警告
strpos(); // 触发警告
// 获取最后错误
$lastError = $logger->getLastError();
echo "<h4>最后错误信息:</h4>";
echo "<pre>" . print_r($lastError, true) . "</pre>";
// 获取所有记录的错误
echo "<h4>所有记录的错误: (" . count($logger->getErrors()) . " 个)</h4>";
echo "<pre>" . print_r($logger->getErrors(), true) . "</pre>";
error_get_last() 只返回最近发生的错误信息。如果需要获取所有错误,需要使用自定义错误处理器。@ 错误抑制操作符时,被抑制的错误不会被 error_get_last() 捕获。error_get_last() 仍然可以获取到最后发生的错误。register_shutdown_function() 结合 error_get_last() 捕获。error_get_last() 捕获。在应用程序中记录最后一个错误信息,便于调试和问题追踪
在自定义错误处理器中获取错误的详细信息,提供友好的用户界面
在API接口中返回详细的错误信息,便于客户端调试
致命错误(Fatal Error)无法被set_error_handler()捕获,但可以在register_shutdown_function()中使用error_get_last()获取:
<?php
register_shutdown_function(function() {
$error = error_get_last();
if ($error && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) {
// 处理致命错误
error_log("致命错误: " . $error['message']);
}
});
使用@抑制操作符结合error_get_last()获取文件操作失败的详细信息:
<?php
function safeFileOperation($filepath) {
// 使用@抑制错误
$result = @file_get_contents($filepath);
if ($result === false) {
$error = error_get_last();
// 记录或处理错误
return ['success' => false, 'error' => $error['message'] ?? '未知错误'];
}
return ['success' => true, 'content' => $result];
}
在开发环境中收集错误信息用于调试:
<?php
class DebugCollector {
private static $errors = [];
public static function collect() {
$error = error_get_last();
if ($error) {
self::$errors[] = [
'error' => $error,
'backtrace' => debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS),
'timestamp' => microtime(true)
];
}
}
public static function getErrors() {
return self::$errors;
}
}
// 注册收集器
register_shutdown_function(['DebugCollector', 'collect']);