error_reporting() 是PHP内置的错误处理函数,用于设置或获取当前脚本的错误报告级别。它控制PHP应该报告哪些类型的错误,是调试和错误处理的重要工具。
error_reporting() 只影响错误报告,不控制错误是否显示。要控制错误是否显示,需要使用 ini_set('display_errors', 1) 或修改php.ini。
int error_reporting([int $level])
当传入参数时,设置错误报告级别并返回之前的值;不传参数时,返回当前错误报告级别。
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| $level | int | 可选 | 新的错误报告级别。可以是预定义常量或它们的组合。如果省略,函数返回当前错误报告级别。 |
int - 返回当前(或之前)的错误报告级别,以整数形式表示。
|、&、~)来组合或排除特定错误类型。
PHP定义了多个错误级别常量,可以单独使用或组合使用:
| 值 | 常量 | 描述 | 说明 |
|---|---|---|---|
| 1 | E_ERROR |
致命运行时错误 | 脚本会停止执行 |
| 2 | E_WARNING |
运行时警告 | 非致命错误,脚本继续执行 |
| 4 | E_PARSE |
编译时语法解析错误 | 由解析器生成 |
| 8 | E_NOTICE |
运行时通知 | 表示脚本遇到可能是个错误的情况 |
| 16 | E_CORE_ERROR |
PHP初始化启动过程中的致命错误 | PHP引擎启动时的错误 |
| 32 | E_CORE_WARNING |
PHP初始化启动过程中的警告 | PHP引擎启动时的警告 |
| 64 | E_COMPILE_ERROR |
编译时致命错误 | 由Zend脚本引擎生成 |
| 128 | E_COMPILE_WARNING |
编译时警告 | 由Zend脚本引擎生成 |
| 256 | E_USER_ERROR |
用户生成的错误 | 由trigger_error()生成 |
| 512 | E_USER_WARNING |
用户生成的警告 | 由trigger_error()生成 |
| 1024 | E_USER_NOTICE |
用户生成的通知 | 由trigger_error()生成 |
| 2048 | E_STRICT |
运行时通知 | PHP建议的代码修改,确保代码的兼容性 |
| 4096 | E_RECOVERABLE_ERROR |
可被捕捉的致命错误 | 可由用户定义的错误处理器捕捉 |
| 8192 | E_DEPRECATED |
运行时通知 | 警告代码在未来版本中可能无法工作 |
| 16384 | E_USER_DEPRECATED |
用户生成的弃用警告 | 由trigger_error()生成 |
| 32767 | E_ALL |
所有错误和警告(PHP 5.4+) | 包含除了E_STRICT之外的所有错误 |
E_ALL的值在不同PHP版本中有所不同:
E_STRICT)E_STRICT)E_STRICT,可以使用E_ALL | E_STRICT。
演示如何获取当前错误报告级别,并设置新的级别:
<?php
// 获取当前错误报告级别
$currentLevel = error_reporting();
echo "<div class='alert alert-info'>";
echo "当前错误报告级别: " . $currentLevel;
echo "</div>";
// 显示当前启用的错误类型
echo "<div style='background:#f8f9fa; padding:15px; border:1px solid #ddd; margin:10px 0;'>";
echo "<strong>当前启用的错误类型:</strong><br>";
displayErrorLevels($currentLevel);
echo "</div>";
// 设置新的错误报告级别 - 只显示错误和警告
$oldLevel = error_reporting(E_ERROR | E_WARNING | E_PARSE);
echo "<div class='alert alert-success'>";
echo "已设置新的错误级别: E_ERROR | E_WARNING | E_PARSE<br>";
echo "之前的值: " . $oldLevel;
echo "</div>";
// 测试错误报告
echo "<div style='background:#e7f3ff; padding:10px; border:1px solid #b3d7ff; margin:10px 0;'>";
echo "<strong>测试错误报告:</strong><br>";
// 这会触发警告(如果E_WARNING被启用)
echo $undefinedVariable;
echo "</div>";
// 关闭所有错误报告
error_reporting(0);
echo "<div class='alert alert-warning'>";
echo "已关闭所有错误报告";
echo "</div>";
// 重新测试 - 这次不会有错误显示
echo $undefinedVariable;
// 恢复原始设置
error_reporting($oldLevel);
// 辅助函数:显示启用的错误级别
function displayErrorLevels($level) {
$errorConstants = [
E_ERROR => 'E_ERROR',
E_WARNING => 'E_WARNING',
E_PARSE => 'E_PARSE',
E_NOTICE => 'E_NOTICE',
E_CORE_ERROR => 'E_CORE_ERROR',
E_CORE_WARNING => 'E_CORE_WARNING',
E_COMPILE_ERROR => 'E_COMPILE_ERROR',
E_COMPILE_WARNING => 'E_COMPILE_WARNING',
E_USER_ERROR => 'E_USER_ERROR',
E_USER_WARNING => 'E_USER_WARNING',
E_USER_NOTICE => 'E_USER_NOTICE',
E_STRICT => 'E_STRICT',
E_RECOVERABLE_ERROR => 'E_RECOVERABLE_ERROR',
E_DEPRECATED => 'E_DEPRECATED',
E_USER_DEPRECATED => 'E_USER_DEPRECATED',
];
foreach ($errorConstants as $value => $name) {
if ($level & $value) {
echo "<span style='color:green;'>✓</span> " . $name . " (" . $value . ")<br>";
} else {
echo "<span style='color:red;'>✗</span> " . $name . " (" . $value . ")<br>";
}
}
}
展示一些常用的错误级别组合:
<?php
// 常用的错误级别组合
$errorLevels = [
'关闭所有错误报告' => 0,
'只显示致命错误' => E_ERROR,
'显示错误和警告' => E_ERROR | E_WARNING,
'显示错误、警告和通知' => E_ERROR | E_WARNING | E_NOTICE,
'显示所有错误(PHP 5.4+)' => E_ALL,
'显示所有错误(包含严格模式)' => E_ALL | E_STRICT,
'开发环境推荐' => E_ALL,
'生产环境推荐' => E_ERROR | E_WARNING | E_PARSE,
'排除弃用警告' => E_ALL & ~E_DEPRECATED,
'只显示用户错误' => E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE,
];
echo "<h4>常用的错误级别组合:</h4>";
echo "<table class='table table-bordered'>";
echo "<thead><tr><th>描述</th><th>值</th><th>代码示例</th></tr></thead>";
echo "<tbody>";
foreach ($errorLevels as $description => $level) {
$codeExample = htmlspecialchars("error_reporting($level);");
echo "<tr>";
echo "<td>" . $description . "</td>";
echo "<td>" . $level . "</td>";
echo "<td><code>" . $codeExample . "</code></td>";
echo "</tr>";
}
echo "</tbody></table>";
// 测试不同的错误级别
echo "<h4>测试不同的错误级别:</h4>";
// 1. 开发环境 - 显示所有错误
error_reporting(E_ALL);
ini_set('display_errors', 1);
echo "<div style='background:#e7f3ff; padding:10px; margin:10px 0; border:1px solid #b3d7ff;'>";
echo "<strong>开发环境设置 (E_ALL):</strong><br>";
// 这些都会显示
@$nonexistent; // 静默错误
echo "</div>";
// 2. 生产环境 - 只显示重要错误
error_reporting(E_ERROR | E_WARNING | E_PARSE);
echo "<div style='background:#f8f9fa; padding:10px; margin:10px 0; border:1px solid #ddd;'>";
echo "<strong>生产环境设置 (E_ERROR | E_WARNING | E_PARSE):</strong><br>";
// 只有错误和警告会显示
@$nonexistent; // 静默错误
echo "</div>";
// 3. 排除弃用警告
error_reporting(E_ALL & ~E_DEPRECATED);
echo "<div style='background:#fff3cd; padding:10px; margin:10px 0; border:1px solid #ffeaa7;'>";
echo "<strong>排除弃用警告 (E_ALL & ~E_DEPRECATED):</strong><br>";
echo "弃用警告将被隐藏";
echo "</div>";
在应用程序入口点设置错误报告:
<?php
// application/bootstrap.php
// 根据环境设置错误报告
function setupErrorReporting() {
// 定义应用环境
$environment = getenv('APP_ENV') ?: 'production';
if ($environment === 'development' || $environment === 'testing') {
// 开发环境 - 显示所有错误
error_reporting(E_ALL);
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
ini_set('log_errors', 1);
ini_set('error_log', __DIR__ . '/../logs/development.log');
} else {
// 生产环境 - 不显示错误,但记录到日志
error_reporting(E_ERROR | E_WARNING | E_PARSE);
ini_set('display_errors', 0);
ini_set('display_startup_errors', 0);
ini_set('log_errors', 1);
ini_set('error_log', __DIR__ . '/../logs/production.log');
}
// 设置自定义错误处理器
set_error_handler('customErrorHandler');
// 设置异常处理器
set_exception_handler('customExceptionHandler');
// 注册关闭函数以捕获致命错误
register_shutdown_function('shutdownHandler');
}
// 调用设置函数
setupErrorReporting();
// 模拟自定义错误处理器
function customErrorHandler($errno, $errstr, $errfile, $errline) {
// 记录错误到文件
$logMessage = sprintf(
"[%s] [%s] %s in %s on line %d\n",
date('Y-m-d H:i:s'),
getErrorTypeName($errno),
$errstr,
$errfile,
$errline
);
error_log($logMessage, 3, 'error.log');
// 如果环境是开发,显示错误
if (getenv('APP_ENV') === 'development') {
echo "<div style='background:#f8d7da; border:1px solid #f5c6cb; padding:10px; margin:10px 0;'>";
echo "<strong>错误:</strong> " . htmlspecialchars($errstr) . "<br>";
echo "<strong>位置:</strong> " . $errfile . " 第 " . $errline . " 行";
echo "</div>";
}
// 不要执行PHP内置错误处理器
return true;
}
function customExceptionHandler($exception) {
// 处理未捕获的异常
error_log("未捕获异常: " . $exception->getMessage(), 3, 'error.log');
}
function shutdownHandler() {
$error = error_get_last();
if ($error && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) {
error_log("致命错误: " . $error['message'], 3, 'error.log');
}
}
function getErrorTypeName($type) {
$errorTypes = [
1 => 'E_ERROR',
2 => 'E_WARNING',
8 => 'E_NOTICE',
256 => 'E_USER_ERROR',
512 => 'E_USER_WARNING',
1024 => 'E_USER_NOTICE',
4096 => 'E_RECOVERABLE_ERROR',
8192 => 'E_DEPRECATED',
16384 => 'E_USER_DEPRECATED',
];
return $errorTypes[$type] ?? "UNKNOWN($type)";
}
echo "<div class='alert alert-success'>";
echo "错误报告已根据环境配置: " . (getenv('APP_ENV') ?: 'production');
echo "</div>";
在特定代码块中临时修改错误报告级别:
<?php
// 保存当前错误级别
$originalErrorLevel = error_reporting();
echo "<div class='alert alert-info'>";
echo "原始错误级别: " . $originalErrorLevel;
echo "</div>";
// 示例1:临时关闭错误报告
echo "<h4>1. 临时关闭错误报告:</h4>";
// 保存当前级别
$previousLevel = error_reporting(0);
// 执行可能产生错误的代码
$result = @file_get_contents('non_existent_file.txt'); // 使用@抑制错误
if ($result === false) {
echo "<div style='background:#f8f9fa; padding:10px; margin:10px 0;'>";
echo "文件读取失败,但错误被抑制";
echo "</div>";
}
// 恢复之前的级别
error_reporting($previousLevel);
// 示例2:临时开启调试模式
echo "<h4>2. 临时开启所有错误报告:</h4>";
$previousLevel = error_reporting(E_ALL);
ini_set('display_errors', 1);
// 执行调试代码
echo "<div style='background:#e7f3ff; padding:10px; border:1px solid #b3d7ff;'>";
echo "<strong>调试信息:</strong><br>";
$debugVar = "调试变量";
echo $undefinedVar; // 这会显示Notice
echo "</div>";
// 恢复之前的级别
error_reporting($previousLevel);
ini_set('display_errors', 0);
// 示例3:使用try-catch控制错误级别
echo "<h4>3. 在try-catch块中控制错误级别:</h4>";
function safelyExecute($callback) {
// 保存当前错误级别
$oldLevel = error_reporting(0);
$oldDisplayErrors = ini_get('display_errors');
ini_set('display_errors', 0);
try {
$result = $callback();
return ['success' => true, 'result' => $result];
} catch (Exception $e) {
return ['success' => false, 'error' => $e->getMessage()];
} finally {
// 无论是否发生异常,都恢复原始设置
error_reporting($oldLevel);
ini_set('display_errors', $oldDisplayErrors);
}
}
// 测试安全执行
$result = safelyExecute(function() {
// 这里可能产生错误
return file_get_contents('non_existent_file.txt');
});
echo "<div style='background:" . ($result['success'] ? '#d4edda' : '#f8d7da') . "; padding:10px; border:1px solid " . ($result['success'] ? '#c3e6cb' : '#f5c6cb') . ";'>";
echo "<strong>执行结果:</strong> ";
if ($result['success']) {
echo "成功";
} else {
echo "失败: " . htmlspecialchars($result['error']);
}
echo "</div>";
// 恢复原始设置
error_reporting($originalErrorLevel);
使用位运算符操作错误级别掩码:
<?php
// 初始错误级别
error_reporting(E_ALL);
$currentLevel = error_reporting();
echo "<div class='alert alert-info'>";
echo "初始错误级别: " . $currentLevel;
echo "</div>";
// 1. 添加错误类型
echo "<h4>1. 添加错误类型:</h4>";
// 添加E_DEPRECATED到当前级别
$newLevel = error_reporting($currentLevel | E_DEPRECATED);
echo "<div style='background:#e7f3ff; padding:10px; margin:10px 0;'>";
echo "添加E_DEPRECATED: " . error_reporting() . "<br>";
echo "之前的级别: " . $newLevel;
echo "</div>";
// 2. 移除错误类型
echo "<h4>2. 移除错误类型:</h4>";
// 从当前级别移除E_NOTICE
$currentLevel = error_reporting();
$newLevel = error_reporting($currentLevel & ~E_NOTICE);
echo "<div style='background:#fff3cd; padding:10px; margin:10px 0;'>";
echo "移除E_NOTICE: " . error_reporting() . "<br>";
echo "之前的级别: " . $newLevel;
echo "</div>";
// 3. 检查是否包含特定错误类型
echo "<h4>3. 检查是否包含特定错误类型:</h4>";
function isErrorTypeEnabled($errorType) {
$currentLevel = error_reporting();
return ($currentLevel & $errorType) === $errorType;
}
$errorTypes = [
'E_ERROR' => E_ERROR,
'E_WARNING' => E_WARNING,
'E_NOTICE' => E_NOTICE,
'E_DEPRECATED' => E_DEPRECATED,
'E_STRICT' => E_STRICT,
];
echo "<table class='table table-bordered'>";
echo "<thead><tr><th>错误类型</th><th>是否启用</th></tr></thead>";
echo "<tbody>";
foreach ($errorTypes as $name => $type) {
$enabled = isErrorTypeEnabled($type) ? '是' : '否';
$color = isErrorTypeEnabled($type) ? 'green' : 'red';
echo "<tr>";
echo "<td>" . $name . "</td>";
echo "<td style='color:" . $color . ";'><strong>" . $enabled . "</strong></td>";
echo "</tr>";
}
echo "</tbody></table>";
// 4. 切换错误类型(开启/关闭)
echo "<h4>4. 切换错误类型:</h4>";
function toggleErrorType($errorType) {
$currentLevel = error_reporting();
if (($currentLevel & $errorType) === $errorType) {
// 如果已启用,则关闭
error_reporting($currentLevel & ~$errorType);
return "已关闭";
} else {
// 如果已禁用,则开启
error_reporting($currentLevel | $errorType);
return "已开启";
}
}
// 切换E_NOTICE
$result = toggleErrorType(E_NOTICE);
echo "<div class='alert " . ($result === '已开启' ? 'alert-success' : 'alert-warning') . "'>";
echo "E_NOTICE: " . $result;
echo "</div>";
// 5. 创建自定义错误级别组合
echo "<h4>5. 自定义错误级别组合:</h4>";
// 只显示用户错误,排除弃用警告
$customLevel = E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE;
$customLevel &= ~E_DEPRECATED; // 排除弃用警告
$customLevel &= ~E_USER_DEPRECATED; // 排除用户弃用警告
error_reporting($customLevel);
echo "<div style='background:#d1ecf1; padding:10px; border:1px solid #bee5eb;'>";
echo "自定义错误级别: " . error_reporting();
echo "</div>";
创建一个完整的错误报告配置类:
<?php
/**
* 错误报告配置类
*/
class ErrorReportingConfig {
private static $environments = [
'development' => [
'error_reporting' => E_ALL,
'display_errors' => 1,
'display_startup_errors' => 1,
'log_errors' => 1,
'error_log' => 'logs/development.log',
],
'testing' => [
'error_reporting' => E_ALL,
'display_errors' => 1,
'display_startup_errors' => 1,
'log_errors' => 1,
'error_log' => 'logs/testing.log',
],
'staging' => [
'error_reporting' => E_ERROR | E_WARNING | E_PARSE | E_USER_ERROR | E_USER_WARNING,
'display_errors' => 0,
'display_startup_errors' => 0,
'log_errors' => 1,
'error_log' => 'logs/staging.log',
],
'production' => [
'error_reporting' => E_ERROR | E_WARNING | E_PARSE,
'display_errors' => 0,
'display_startup_errors' => 0,
'log_errors' => 1,
'error_log' => 'logs/production.log',
],
];
/**
* 配置错误报告
*/
public static function configure($environment = null) {
if ($environment === null) {
$environment = self::detectEnvironment();
}
if (!isset(self::$environments[$environment])) {
throw new InvalidArgumentException("未知的环境: " . $environment);
}
$config = self::$environments[$environment];
// 应用配置
error_reporting($config['error_reporting']);
ini_set('display_errors', $config['display_errors']);
ini_set('display_startup_errors', $config['display_startup_errors']);
ini_set('log_errors', $config['log_errors']);
if (!empty($config['error_log'])) {
// 确保日志目录存在
$logDir = dirname($config['error_log']);
if (!is_dir($logDir)) {
mkdir($logDir, 0755, true);
}
ini_set('error_log', $config['error_log']);
}
return [
'environment' => $environment,
'config' => $config,
];
}
/**
* 检测环境
*/
private static function detectEnvironment() {
// 1. 检查环境变量
if (getenv('APP_ENV')) {
return getenv('APP_ENV');
}
// 2. 检查HTTP_HOST(Web环境)
if (isset($_SERVER['HTTP_HOST'])) {
$host = $_SERVER['HTTP_HOST'];
if (strpos($host, 'localhost') !== false ||
strpos($host, '127.0.0.1') !== false ||
strpos($host, 'dev.') === 0 ||
strpos($host, 'test.') === 0) {
return 'development';
}
if (strpos($host, 'staging.') === 0 ||
strpos($host, 'qa.') === 0) {
return 'staging';
}
}
// 3. 默认生产环境
return 'production';
}
/**
* 获取当前配置
*/
public static function getCurrentConfig() {
return [
'error_reporting' => error_reporting(),
'display_errors' => ini_get('display_errors'),
'display_startup_errors' => ini_get('display_startup_errors'),
'log_errors' => ini_get('log_errors'),
'error_log' => ini_get('error_log'),
];
}
/**
* 显示当前配置
*/
public static function displayCurrentConfig() {
$config = self::getCurrentConfig();
$output = "<div style='background:#f8f9fa; padding:15px; border:1px solid #ddd;'>";
$output .= "<h4>当前错误报告配置:</h4>";
$output .= "<table class='table table-sm table-bordered'>";
foreach ($config as $key => $value) {
$output .= "<tr>";
$output .= "<td><strong>" . $key . "</strong></td>";
$output .= "<td>" . htmlspecialchars($value) . "</td>";
$output .= "</tr>";
}
$output .= "</table>";
$output .= "</div>";
return $output;
}
}
// 使用示例
echo "<h4>自动检测并配置环境:</h4>";
// 自动检测环境并配置
$config = ErrorReportingConfig::configure();
echo "<div class='alert alert-success'>";
echo "已配置为: " . $config['environment'] . " 环境";
echo "</div>";
// 显示当前配置
echo ErrorReportingConfig::displayCurrentConfig();
// 测试不同环境
echo "<h4>手动设置不同环境:</h4>";
$environments = ['development', 'testing', 'staging', 'production'];
foreach ($environments as $env) {
try {
ErrorReportingConfig::configure($env);
echo "<div class='alert alert-info'>";
echo "<strong>" . ucfirst($env) . "环境:</strong> ";
echo "错误报告级别: " . error_reporting();
echo "</div>";
} catch (Exception $e) {
echo "<div class='alert alert-danger'>" . $e->getMessage() . "</div>";
}
}
// 恢复为自动检测的环境
ErrorReportingConfig::configure();
设置:E_ALL 或 E_ALL | E_STRICT
目的:捕获所有可能的错误和警告,便于调试
error_reporting(E_ALL);
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
设置:E_ERROR | E_WARNING | E_PARSE
目的:只显示关键错误,记录日志但不显示给用户
error_reporting(E_ERROR | E_WARNING | E_PARSE);
ini_set('display_errors', 0);
ini_set('log_errors', 1);
ini_set('error_log', '/path/to/error.log');
技巧:在需要调试的代码块前后临时修改错误级别
$oldLevel = error_reporting(E_ALL); // 调试代码 error_reporting($oldLevel);
技巧:使用位运算符过滤特定类型的错误
// 排除弃用警告 error_reporting(E_ALL & ~E_DEPRECATED); // 只显示用户错误 error_reporting(E_USER_ERROR | E_USER_WARNING);
error_reporting()控制报告哪些错误,display_errors控制是否显示错误,两者需要配合使用error_reporting()控制@错误控制运算符可以临时抑制错误,不受error_reporting()影响E_ALL的值在不同PHP版本中不同,使用E_ALL | E_STRICT确保包含所有错误