PHP set_error_handler()函数使用详解(示例)


Posted in PHP onNovember 12, 2013

我们写程序,难免会有问题(是经常会遇到问题 ),而PHP遇到错误时,就会给出出错脚本的位置、行数和原因。有很多人说,这并没有什么大不了。确实,在调试程序阶段,这确实是没啥的,而且我认为给出错误路径是必要的。
但泄露了实际路径的后果是不堪设想的,对于某些入侵者,这个信息可是非常重要,而事实上现在有很多的服务器都存在这个问题。有些网管干脆把PHP配置文件中的display_errors设置为Off来解决(貌似我们就是这样做的),但本人认为这个方法过于消极。
有些时候,我们的确需要PHP返回错误的信息以便调试。而且在出错时也可能需要给用户一个交待,甚至导航到另一页面。那么,有啥解决办法呢?
set_error_handler()
PHP从4.1.0开始提供了自定义错误处理句柄的功能函数set_error_handler(),但很少数脚本编写者知道。set_error_handler这个函数可以很好地防止错误路径泄露,当然还有其它更多的作用。
可以用来屏蔽错误。 出现错误一来会把一些信息暴漏给用户,极有可能成为黑客攻击你网站的工具。 二来让用户觉得你的水平很挫。
可以记下错误的信息, 及时发现一些生产环境的出现的问题。
可以做相应的处理, 出错的时候可以显示跳转到预先定义好的出错页面,提供更好的用户体验。
可以作为调试工具, 一些时候必须在生产环境调试一些东西, 但又不想影响正在使用的用户。
set_error_handler的使用方法如下:

string set_error_handler ( callback error_handler [, int error_types])

现在我们就用自定义的错误处理把实际路径过滤掉。假设有一个变量$admin,我们是用来判断访问者是否是管理员的(可以通过IP或者登录的用户id来做这个判断)
//admin为管理员的身份判定,true为管理员。  
//自定义的错误处理函数一定要有这4个输入变量$errno,$errstr,$errfile,$errline,否则无效。  
function my_error_handler($errno,$errstr,$errfile,$errline)  
{  
    //如果不是管理员就过滤实际路径  
    if(!admin)  
    {  
        $errfile=str_replace(getcwd(),"",$errfile);  
        $errstr=str_replace(getcwd(),"",$errstr);  
    }  
    switch($errno)  
    {  
        case E_ERROR:  
        echo "ERROR: [ID $errno] $errstr (Line: $errline of $errfile) \n";  
        echo "程序已经停止运行,请联系管理员。";  
        //遇到Error级错误时退出脚本  
        exit;  
        break;          case E_WARNING:  
        echo "WARNING: [ID $errno] $errstr (Line: $errline of $errfile) \n";  
        break;  
        default:  
        //不显示Notice级的错误  
        break;  
    }  
} 

这样就自定义了一个错误处理函数,那么怎么把错误的处理交给这个自定义函数呢?
// 应用到类  
set_error_handler(array(&$this,"appError"));  //示例的做法  
set_error_handler("my_error_handler"); 

so easy,这样,就可以很好地解决安全和调试方便的矛盾了。而且你还可以花点心思,使错误提示更加美观以配合网站的风格。
原作者给出了两点需要注意的地方,我也放出来吧,希望引起广大同胞们的注意:
1、E_ERROR、E_PARSE、E_CORE_ERROR、E_CORE_WARNING、 E_COMPILE_ERROR、E_COMPILE_WARNING是不会被这个句柄处理的,也就是会用最原始的方式显示出来。不过出现这些错误都是编 译或PHP内核出错,在通常情况下不会发生。
2、使用set_error_handler()后,error_reporting ()将会失效。也就是所有的错误(除上述的错误)都会交给自定义的函数处理。
最后,出一个示例
//先定义一个函数,也可以定义在其他的文件中,再用require()调用  
function myErrorHandler($errno, $errstr, $errfile, $errline)  
{  

 //为了安全起见,不暴露出真实物理路径,下面两行过滤实际路径  
    $errfile=str_replace(getcwd(),"",$errfile);  
    $errstr=str_replace(getcwd(),"",$errstr);  
    switch ($errno) {  
    case E_USER_ERROR:  
     echo "<b>My ERROR</b> [$errno] $errstr<br />\n";  
        echo "  Fatal error on line $errline in file $errfile";  
        echo ", PHP " . PHP_VERSION . " (" . PHP_OS . ")<br />\n";  
        echo "Aborting...<br />\n";  
        exit(1);  
        break;  
    case E_USER_WARNING:  
        echo "<b>My WARNING</b> [$errno] $errstr<br />\n";  
        break;  
    case E_USER_NOTICE:  
        echo "<b>My NOTICE</b> [$errno] $errstr<br />\n";  
        break;  
    default:  
        echo "Unknown error type: [$errno] $errstr<br />\n";  
        break;  
    }  
    /* Don't execute PHP internal error handler */  
    return true;  
}  
//下面开始连接MYSQL服务器,我们故意指定MYSQL端口为3333,实际为3306。  
$link_id=@mysql_pconnect("localhost:3333","root","password");  
set_error_handler(myErrorHandler);  
if (!$link_id) {  
    trigger_error("出错了", E_USER_ERROR);  
} 
PHP 相关文章推荐
如何给phpadmin一个保护
Oct 09 PHP
php对图像的各种处理函数代码小结
Jul 08 PHP
解密ThinkPHP3.1.2版本之模板继承
Jun 19 PHP
分享最受欢迎的5款PHP框架
Nov 27 PHP
php数字运算验证码的实现代码
Jul 30 PHP
Linux系统下PHP-FPM的安装和配置教程
Aug 17 PHP
ThinkPHP模板Volist标签嵌套循环输出多维数组的方法
Mar 23 PHP
Yii2.0多文件上传实例说明
Jul 24 PHP
PHP时间日期增减操作示例【date strtotime实现加一天、加一月等操作】
Dec 21 PHP
php文件上传原理与实现方法详解
Dec 20 PHP
PHP与Web页面的交互示例详解一
Aug 04 PHP
PHP的imageTtfText()函数深入详解
Mar 03 PHP
php inc文件使用的风险和注意事项
Nov 12 #PHP
php防止SQL注入详解及防范
Nov 12 #PHP
php session劫持和防范的方法
Nov 12 #PHP
php后门URL的防范
Nov 12 #PHP
php打开远程文件的方法和风险及解决方法
Nov 12 #PHP
php使用exec shell命令注入的方法讲解
Nov 12 #PHP
PHP使用PHPMailer发送邮件的简单使用方法
Nov 12 #PHP
You might like
咖啡是不是喝了会上瘾?咖啡是必须品吗!
2021/03/04 新手入门
PHP删除HTMl标签的实现代码
2013/06/30 PHP
再推荐十款免费的php开发工具
2015/11/09 PHP
全新Mac配置PHP开发环境教程
2016/02/03 PHP
PHP+JQuery+Ajax实现分页方法详解
2016/08/06 PHP
PHP5.4起内置web服务器使用方法
2016/08/09 PHP
老生常谈PHP数组函数array_merge(必看篇)
2017/05/25 PHP
广告切换效果(缓动切换)
2009/05/27 Javascript
JS 控制小数位数的实现代码
2011/08/02 Javascript
取得窗口大小 兼容所有浏览器的js代码
2011/08/09 Javascript
IE与FireFox中的childNodes区别
2011/10/20 Javascript
利用Javascript判断操作系统的类型实现不同操作系统下的兼容性
2013/01/29 Javascript
IE的fireEvent方法概述及应用
2013/02/22 Javascript
javascript标签在页面中的位置探讨
2013/04/11 Javascript
基于IE下ul li 互相嵌套时的bug,排查,解决过程以及心得介绍
2013/05/07 Javascript
AngularJS基础学习笔记之指令
2015/05/10 Javascript
jquery+php随机生成红包金额数量代码分享
2015/08/27 Javascript
jQuery leonaScroll 1.1 自定义滚动条插件(推荐)
2016/09/17 Javascript
js 模仿锚点定位的实现方法
2016/11/19 Javascript
JavaScript编写九九乘法表(两种任选)
2017/02/04 Javascript
Node.js使用orm2进行update操作时关联字段无法修改的解决方法
2017/06/13 Javascript
js排序与重组的实例讲解
2017/08/28 Javascript
JS模拟实现哈希表及应用详解
2018/05/04 Javascript
Vue中插入HTML代码的方法
2018/09/21 Javascript
vue-cli3 karma单元测试的实现
2019/01/18 Javascript
vue实现验证用户名是否可用
2021/01/20 Vue.js
Python 按比例获取样本数据或执行任务的实现代码
2020/12/03 Python
Python就将所有的英文单词首字母变成大写
2021/02/12 Python
英国最大的电子产品和家电零售企业:Currys PC World
2016/09/24 全球购物
美国花园雕像和家居装饰网上商店:Design Toscano
2019/03/09 全球购物
Prototype中如何为一个元素添加一个方法
2014/12/08 面试题
优秀交警事迹材料
2014/01/26 职场文书
总经理岗位职责
2015/02/04 职场文书
2015年教师节感言
2015/08/03 职场文书
青少年法制教育心得体会
2016/01/14 职场文书
Windows server 2022创建创建林、域树、子域的步骤
2022/06/25 Servers