PHP 错误处理
PHP 默认处理错误的方式,就是一旦发生错误,就把错误信息返回给浏览器,这条消息带有文件名、行号以及描述错误的消息
显然,在开发和测试过程中,这是有利的,我们可以很方便的得知错误发生的地方并且尽快修复
但在生产环境上,是不允许这么做的,不仅会造成不好的用户体验,更有可能会泄露一些信息,被黑客利用
PHP 错误处理
错误处理在任何编程语言中,都是很重要的一个部分
如果我们的代码缺少错误检测编码,不仅程序结构看上去不严谨,更是为安全风险敞开了大门
本章节我们就来学习 PHP 语言中处理错误的方法
我们将学习到三种不同的错误处理方式
-
简单的 "die()" 语句
-
自定义错误和错误触发器
-
错误报告
最简单的错误处理:使用 die() 函数
假如我们的 PHP 服务从一个 文本文件 demo.txt
中读取程序
代码可能是下面这样的
php_error_1.php
<?php $fp=fopen("demo.txt","r");
如果文件不存在,就会得到下面这样的错误
Warning: fopen(demo.txt) [function.fopen]: failed to open stream: No such file or directory in /php_error_1.php on line 2
这显然不是我们所希望的,因为用户根本就看不懂,他们会茫然无措,另一方面,也暴露了当前文件的路径,造成安全上的隐患
为了避免用户得到类似上面的错误消息,可以访问文件之前检测该文件是否存在:
<?php if(!file_exists("welcome.txt")) { die("文件不存在"); } else { $file=fopen("welcome.txt","r"); }
现在,如果文件不存在,就会得到下面这样的错误消息:
文件不存在
相比之前的代码,上面的代码更有效,这是由于它采用了一个简单的错误处理机制在错误之后终止了脚本
但是,简单地终止脚本并不总是恰当的方式
创建自定义错误处理器
使用 die()
函数处理错误就是暴力直接停止脚本运行,在某些关键地方的确是最好的方式
但多数情况下我们仍然希望脚本能正常运行直至结束
PHP 允许用户可以自定义错误处理器来处理发生的错误
PHP 为此提供了 set_error_handler
函数来定义错误拦截器,当发生错误时调用用户自定义的错误处理函数
语法
PHP 自定义函数必须符合以下语法格式
error_function(error_level,error_message, error_file,error_line,error_context)
用户自定义的错误处理函数必须至少接收两个参数(error level 和 error message)
且最多接收五个参数 (可选的:file, line-number 和 error context )
参数列表
参数 | 描述 |
---|---|
error_level | 必需。为用户定义的错误规定错误报告级别 必须是一个数字 参见下面的表格:错误报告级别 |
error_message | 必需。为用户定义的错误规定错误消息 |
error_file | 可选。规定错误发生的文件名 |
error_line | 可选。规定错误发生的行号 |
error_context | 可选。包含了发生错误时上下文中的每个变量和值的数组 |
错误报告级别
下面列出了 PHP 支持的错误报告级别
错误报告级别是用户自定义的错误处理程序处理的不同类型的错误
常量 | 描述 |
---|---|
E_WARNING | 非致命的 run-time 错误,不暂停脚本执行 |
E_NOTICE | run-time 通知。在脚本发现可能有错误时发生,但也可能在脚本正常运行时发生 |
E_USER_ERROR | 致命的用户生成的错误 一般情况下是调用函数 trigger_error() 设置的 E_ERROR |
E_USER_WARNING | 非致命的用户生成的警告 一般情况下是调用函数 trigger_error() 设置的 E_WARNING |
E_USER_NOTICE | 用户生成的通知 一般情况下是调用函数 trigger_error() 设置的 E_NOTICE |
E_RECOVERABLE_ERROR | 可捕获的致命错误。类似 E_ERROR,但可被用户定义的处理程序捕获。(参见 set_error_handler()) |
E_ALL | 所有错误和警告 ( 在 PHP 5.4 中,E_STRICT 成为 E_ALL 的一部分 ) |
现在,我们创建一个自己的错误处理函数 custom_error
<?php function custom_error($errno, $errstr) { echo "<b>Error:</b>[$errno] $errstr<br>"; echo "脚本结束"; die(); }
这是一个最简单的错误处理函数,但错误发生时,它会取得错误级别和错误消息,然后它会输出错误级别和消息,并终止脚本
现在,我们创建了一个一个错误处理函数,我们需要确定在何时触发该函数
设置错误处理程序
PHP 的默认错误处理程序是内建的错误处理程序
但我们想用自己的定义的 custom_error
函数来代替默认错误处理程序
PHP 允许修改错误处理程序,使其仅应用到某些错误,这样脚本就能以不同的方式来处理不同的错误
但一般情况下,都是针对所有错误来使用我们自定义的错误处理程序
<?php set_error_handler("custom_error");
由于我们希望我们的自定义函数能处理所有错误,set_error_handler() 仅需要一个参数
可以添加第二个参数来规定错误级别
范例
现在我们使用一个范例来演示上面定义的错误处理函数
php_error_2.php
<?php // 错误处理函数 function custom_error($errno, $errstr) { echo "<b>Error:</b> [$errno] $errstr"; } // 设置错误处理函数 set_error_handler("custom_error"); // 触发错误 echo($test); echo '<p>PHP 基础教程 - 简单教程(www.twle.cn)</p>';
运行以上 PHP 范例,输出结果如下
手动触发错误
有时候我们可能需要自己手动触发错误,比如在用户输入数据的位置
PHP 提供了 trigger_error()
函数来触发错误
范例
下面这个范例,如果 "test" 变量大于 "1",就会发生错误
php_error_3.php
<?php echo '<p>PHP 基础教程 - 简单教程(www.twle.cn)</p>'; $test=2; if ($test>1) { trigger_error("变量值必须小于等于 1"); }
运行以上 PHP 范例,输出结果如下
我们可以在脚本中任何位置触发错误
而且我们可以通过传递第二个参数来规定所触发的错误级别
可以设置的错误级别
错误级别 | 描述 |
---|---|
E_USER_ERROR | 致命的用户生成的 run-time 错误 错误无法恢复,脚本执行被中断 |
E_USER_WARNING | 非致命的用户生成的 run-time 警告 脚本执行不被中断 |
E_USER_NOTICE | 默认。用户生成的 run-time 通知 在脚本发现可能有错误时发生,但也可能在脚本正常运行时发生 |
范例
下面的范例,如果 "test" 变量大于 "1",则发生 E_USER_WARNING 错误
如果发生了 E_USER_WARNING 错误,我们将使用我们自定义的错误处理程序并结束脚本
php_error_4.php
<?php // 错误处理函数 function custom_error($errno, $errstr) { echo "<b>Error:</b> [$errno] $errstr<br>"; echo "脚本结束"; die(); } // 设置错误处理函数 set_error_handler("custom_error",E_USER_WARNING); echo '<p>PHP 基础教程 - 简单教程(www.twle.cn)</p>'; // 触发错误 $test=2; if ($test > 1) { trigger_error("变量值必须小于等于 1",E_USER_WARNING); }
运行以上 PHP 范例,输出结果如下
错误记录
PHP 提供了 error_log()
函数向指定的文件或远程目的地发送错误记录
默认情况下,PHP 会向服务器的记录系统或文件发送错误记录
PHP 会将错误日志发送到 php.ini
中的 error_log
配置中
将错误发送到电子邮件是一种获得指定错误的通知的好办法
通过 EMail 发送错误消息
在下面的例子中,如果特定的错误发生,我们将发送带有错误消息的电子邮件,并结束脚本:
php_error_5.php
<?php // 错误处理函数 function custom_error($errno, $errstr) { echo "<b>Error:</b> [$errno] $errstr<br>"; echo "已通知网站管理员"; error_log("Error: [$errno] $errstr",1, "someone@example.com","From: webmaster@example.com"); } echo '<p>PHP 基础教程 - 简单教程(www.twle.cn)</p>'; // 设置错误处理函数 set_error_handler("custom_error",E_USER_WARNING); // 触发错误 $test=2; if ($test>1) { trigger_error("变量值必须小于等于 1",E_USER_WARNING); }
运行以上 PHP 范例,输出结果如下
接收自以上代码的邮件如下所示:
Error: [512] 变量值必须小于等于 1
这个方法不适合所有的错误
常规错误应当通过使用默认的 PHP 记录系统在服务器上进行记录