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 相关文章推荐
不用数据库的多用户文件自由上传投票系统(1)
Oct 09 PHP
PHP伪静态页面函数附使用方法
Jun 20 PHP
php 表单数据的获取代码
Mar 10 PHP
PHP编程最快明白(第一讲 软件环境和准备工作)
Oct 25 PHP
PHP实现的多彩标签效果代码分享
Aug 21 PHP
Yii实现多数据库主从读写分离的方法
Dec 29 PHP
php去除字符串中空字符的常用方法小结
Mar 17 PHP
PHP的中使用非缓冲模式查询数据库的方法
Feb 05 PHP
PHP生成腾讯云COS接口需要的请求签名
May 20 PHP
PHP文件操作实例总结【文件上传、下载、分页】
Dec 08 PHP
PHP压缩图片功能的介绍
Mar 21 PHP
laravel框架邮箱认证实现方法详解
Nov 22 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
浅析PHP水印技术
2007/02/14 PHP
php5 pdo新改动加载注意事项
2008/09/11 PHP
php实现字符串翻转的方法
2015/03/27 PHP
thinkPHP中验证码的简单实现方法
2016/12/05 PHP
php实现二叉树中和为某一值的路径方法
2018/10/14 PHP
jQuery学习笔记(1)--用jQuery实现异步通信(用json传值)具体思路
2013/04/08 Javascript
cookie中的path与domain属性详解
2013/12/18 Javascript
js利用prototype调用Array的slice方法示例
2014/06/09 Javascript
jquery判断浏览器后退时候弹出消息的方法
2014/08/11 Javascript
javascript实现字符串反转的方法
2015/02/05 Javascript
javascript控制层显示或隐藏的方法
2015/07/22 Javascript
jQuery中prepend()方法使用详解
2015/08/11 Javascript
通用javascript代码判断版本号是否在版本范围之间
2015/11/29 Javascript
详解AngularJS中的http拦截
2016/02/09 Javascript
老生常谈JQuery data方法的使用
2016/09/09 Javascript
jquery实现tab键进行选择后enter键触发click行为
2017/03/29 jQuery
Bootstrap.css与layDate日期选择样式起冲突的解决办法
2017/04/07 Javascript
浅谈node的事件机制
2017/10/09 Javascript
解析Vue2 dist 目录下各个文件的区别
2017/11/22 Javascript
基于Node.js实现压缩和解压缩的方法
2018/02/13 Javascript
实例讲解Vue.js中router传参
2018/04/22 Javascript
Vue中的字符串模板的使用
2018/05/17 Javascript
js数据类型检测总结
2018/08/05 Javascript
深入学习JavaScript 高阶函数
2019/06/11 Javascript
Vue.use()在new Vue() 之前使用的原因浅析
2019/08/26 Javascript
JavaScript实现背景自动切换小案例
2019/09/27 Javascript
[18:20]DOTA2 HEROS教学视频教你分分钟做大人-昆卡
2014/06/11 DOTA
[24:42]VP vs TNC Supermajor小组赛B组 BO3 第三场 6.2
2018/06/03 DOTA
python numpy 反转 reverse示例
2019/12/04 Python
python实现粒子群算法
2020/10/15 Python
idealfit英国:世界领先的女性健身用品和运动衣物品牌
2017/11/25 全球购物
Booking.com西班牙:全球酒店预订
2018/03/30 全球购物
班组长岗位职责
2014/03/03 职场文书
党员干部廉政承诺书
2015/04/28 职场文书
付款证明格式范文
2015/06/19 职场文书
传单、海报早OUT了,另类传单营销方案送给你!
2019/07/15 职场文书