# PHP自定义错误处理:set_error_handler() 实战
在PHP开发中,错误处理是保证应用程序健壮性的重要环节。今天我们将深入探讨PHP的自定义错误处理机制,特别是`set_error_handler()`函数的使用方法。
## 为什么需要自定义错误处理?
PHP默认的错误处理机制虽然能捕获基本错误,但存在几个明显不足:
1. 错误信息直接输出可能暴露敏感信息
2. 错误格式不符合项目统一日志规范
3. 无法灵活地对不同级别错误采取不同处理方式
## 基本语法
```php
set_error_handler(callable $error_handler, int $error_types = E_ALL | E_STRICT): mixed
```
## 简单示例
```php
function customErrorHandler($errno, $errstr, $errfile, $errline) {
echo "<b>自定义错误:</b> [$errno] $errstr<br>";
echo "错误发生在 $errfile 的第 $errline 行<br>";
}
set_error_handler("customErrorHandler");
// 触发错误
echo $undefinedVar;
```
## 错误级别详解
PHP定义了多种错误级别,常见的有:
- E_ERROR (1) - 致命运行时错误
- E_WARNING (2) - 运行时警告
- E_NOTICE (8) - 运行时通知
- E_USER_ERROR (256) - 用户生成的错误
- E_USER_WARNING (512) - 用户生成的警告
- E_USER_NOTICE (1024) - 用户生成的通知
## 实战:日志记录错误处理
```php
function logErrorHandler($errno, $errstr, $errfile, $errline) {
$log = sprintf(
"[%s] 错误 #%d: %s 在 %s 第 %d 行\n",
date('Y-m-d H:i:s'),
$errno,
$errstr,
$errfile,
$errline
);
file_put_contents('error.log', $log, FILE_APPEND);
// 如果是用户错误或致命错误,发送邮件通知
if ($errno === E_USER_ERROR || $errno === E_ERROR) {
mail('admin@example.com', '网站严重错误', $log);
}
// 返回false将执行PHP内部错误处理
return false;
}
set_error_handler("logErrorHandler", E_ALL);
```
## 高级技巧:上下文信息捕获
```php
function advancedErrorHandler($errno, $errstr, $errfile, $errline, $context) {
$backtrace = debug_backtrace();
$request = print_r($_REQUEST, true);
$log = "[".date('Y-m-d H:i:s')."]\n";
$log .= "错误: [$errno] $errstr\n";
$log .= "位置: $errfile 第 $errline 行\n";
$log .= "请求参数:\n$request\n";
$log .= "调用栈:\n".print_r($backtrace, true)."\n\n";
file_put_contents('advanced_error.log', $log, FILE_APPEND);
// 开发环境显示详细错误,生产环境显示友好页面
if (ENVIRONMENT === 'development') {
echo "<pre>$log</pre>";
} else {
include 'views/error_page.php';
}
return true; // 阻止PHP执行标准错误处理
}
```
## 恢复默认错误处理
```php
restore_error_handler();
```
## 最佳实践建议
1. **区分环境**:开发环境显示详细错误,生产环境记录日志并显示友好页面
2. **错误分类处理**:对不同级别的错误采取不同措施
3. **上下文记录**:尽可能记录错误发生时的上下文信息
4. **性能考虑**:避免在错误处理函数中进行复杂操作
5. **与异常处理结合**:考虑将错误转换为异常统一处理
## 常见问题解答
**Q: set_error_handler能捕获所有PHP错误吗?**
A: 不能捕获E_ERROR、E_PARSE、E_CORE_ERROR等致命错误,这些需要注册shutdown函数处理。
**Q: 自定义错误处理函数应该返回什么?**
A: 返回true表示已处理错误,PHP不再执行标准错误处理;返回false则继续执行PHP内部错误处理。
**Q: 如何在自定义错误处理中获取当前调用栈?**
A: 使用debug_backtrace()函数获取详细的调用栈信息。
通过合理使用`set_error_handler()`,我们可以构建更加健壮、安全的PHP应用程序,提供更好的错误管理和用户体验。