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 相关文章推荐
让你的WINDOWS同时支持MYSQL4,MYSQL4.1,MYSQL5X
Dec 06 PHP
用PHP获取Google AJAX Search API 数据的代码
Mar 12 PHP
php学习笔记之 函数声明
Jun 09 PHP
php继承的一个应用
Sep 06 PHP
深入解析php中的foreach问题
Jun 30 PHP
使用swoole扩展php websocket示例
Feb 13 PHP
php中ltrim()、rtrim()与trim()删除字符空格实例
Nov 25 PHP
如何使用php实现评委评分器
Jul 31 PHP
浅谈使用PHP开发微信支付的流程
Oct 04 PHP
PHP如何根据文件头检测文件类型实例代码
Oct 14 PHP
php链式操作的实现方式分析
Aug 12 PHP
微信小程序结合ThinkPHP5授权登陆后获取手机号
Nov 23 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/06/16 PHP
PHP5 字符串处理函数大全
2010/03/23 PHP
ThinkPHP后台首页index使用frameset时的注意事项分析
2014/08/22 PHP
php使用parse_url和parse_str解析URL
2015/02/22 PHP
微信网页授权(OAuth2.0) PHP 源码简单实现
2016/08/29 PHP
php页面跳转session cookie丢失导致不能登录等问题的解决方法
2016/12/12 PHP
Yii1.1中通过Sql查询进行的分页操作方法
2017/03/16 PHP
TP5框架model常见操作示例小结【增删改查、聚合、时间戳、软删除等】
2020/04/05 PHP
响应鼠标变换表格背景或者颜色的代码
2009/03/30 Javascript
一些常用的JS功能函数(2009-06-04更新)
2009/06/04 Javascript
JavaScript 面向对象的之私有成员和公开成员
2010/05/04 Javascript
基于jQuery的获取标签名的代码
2012/07/16 Javascript
jquery Mobile入门—外部链接切换示例代码
2013/01/08 Javascript
Angularjs中UI Router全攻略
2016/01/29 Javascript
Hammer.js+轮播原理实现简洁的滑屏功能
2016/02/02 Javascript
详解JS几种变量交换方式以及性能分析对比
2016/11/25 Javascript
bootstrap table实现x-editable的行单元格编辑及解决数据Empty和支持多样式问题
2017/08/10 Javascript
Angular4实现动态添加删除表单输入框功能
2017/08/11 Javascript
用JavaScript做简易的购物车的代码示例
2017/10/20 Javascript
JavaScript中变量提升机制示例详解
2019/12/27 Javascript
创建nuxt.js项目流程图解
2020/03/13 Javascript
[01:17]炒鸡美酒第四天TA暴走
2018/06/05 DOTA
Selenium鼠标与键盘事件常用操作方法示例
2018/08/13 Python
对python中类的继承与方法重写介绍
2019/01/20 Python
tensorflow指定CPU与GPU运算的方法实现
2020/04/21 Python
用html5实现语音搜索框的方法
2014/03/18 HTML / CSS
斯德哥尔摩通票:Stockholm Pass
2018/01/09 全球购物
奥地利时尚、美容、玩具和家居之家:Kastner & Öhler
2020/04/26 全球购物
干部行政关系介绍信
2014/01/17 职场文书
化学系大学生自荐信范文
2014/03/01 职场文书
媒矿安全生产承诺书
2014/05/23 职场文书
工商管理自荐书
2014/07/06 职场文书
秋季运动会广播稿(30篇)
2014/09/13 职场文书
毕业证委托书范文
2014/09/26 职场文书
工程催款通知书
2015/04/17 职场文书
SQL Server 数据库实验课第五周——常用查询条件
2021/04/05 SQL Server