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中安装Apache2和PHP4的权威指南
Oct 09 PHP
杏林同学录(五)
Oct 09 PHP
PHP下用rmdir实现删除目录的三种方法小结
Apr 20 PHP
深入理解PHP中的global
Aug 19 PHP
仿dedecms下拉分页样式修改的thinkphp分页类实例
Oct 30 PHP
PHP使用PDO连接ACCESS数据库
Mar 05 PHP
PHP中类的继承和用法实例分析
May 24 PHP
Yii实现Command任务处理的方法详解
Jul 14 PHP
基于yaf框架和uploadify插件,做的一个导入excel文件,查看并保存数据的功能
Jan 24 PHP
PHP图片裁剪与缩放示例(无损裁剪图片)
Feb 08 PHP
lnmp安装多版本PHP共存的方法详解
Aug 02 PHP
PHP 使用位运算实现四则运算的代码
Mar 09 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数据库抽象层 PDO
2011/05/07 PHP
php preg_filter执行一个正则表达式搜索和替换
2012/02/27 PHP
laravel 修改.htaccess文件 重定向public的解决方法
2019/10/12 PHP
Laravel框架处理用户的请求操作详解
2019/12/20 PHP
利用ASP发送和接收XML数据的处理方法与代码
2007/11/13 Javascript
getElementsByTagName vs selectNodes效率 及兼容的selectNodes实现
2010/02/26 Javascript
javascript 解决表单仍然提交即使监听处理函数返回false
2010/03/14 Javascript
javascript 嵌套的函数(作用域链)
2010/03/15 Javascript
提取字符串中年月日的函数代码
2013/11/05 Javascript
javascript获取网页宽高方法汇总
2015/07/19 Javascript
JS实现超精简响应鼠标显示二级菜单代码
2015/09/12 Javascript
jquery可定制的在线UEditor编辑器
2015/11/17 Javascript
JS实现颜色的10进制转化成rgba格式的方法
2017/09/04 Javascript
PHP自动加载autoload和命名空间的应用小结
2017/12/01 Javascript
JS实现的获取银行卡号归属地及银行卡类型操作示例
2019/01/08 Javascript
jQuery实现的卷帘门滑入滑出效果【案例】
2019/02/18 jQuery
ES6知识点整理之Proxy的应用实例详解
2019/04/16 Javascript
layer.open 获取不到表单信息的解决方法
2019/09/26 Javascript
vuex管理状态 刷新页面保持不被清空的解决方案
2019/11/11 Javascript
npx create-react-app xxx创建项目报错的解决办法
2020/02/17 Javascript
如何在JavaScript中创建具有多个空格的字符串?
2020/02/23 Javascript
vue.js实现双击放大预览功能
2020/06/23 Javascript
[04:26]DOTA2上海特锦赛小组赛第二日 TOP10精彩集锦
2016/02/27 DOTA
[01:05:29]DOTA2-DPC中国联赛 正赛 PSG.LGD vs Aster BO3 第二场 1月24日
2021/03/11 DOTA
Python模拟浏览器上传文件脚本的方法(Multipart/form-data格式)
2018/10/22 Python
Python爬取视频(其实是一篇福利)过程解析
2019/08/01 Python
一行Python代码制作动态二维码的实现
2019/09/09 Python
python中添加模块导入路径的方法
2021/02/03 Python
捷科时代的软件测试笔试题
2015/11/09 面试题
电子商务专业推荐信范文
2013/12/02 职场文书
个人简历中自我评价
2014/02/11 职场文书
劳动争议仲裁代理词
2015/05/25 职场文书
2015年团支部年度工作总结
2015/05/27 职场文书
2015国庆66周年宣传语
2015/07/14 职场文书
Java常用函数式接口总结
2021/06/29 Java/Android
Golang 字符串的常见操作
2022/04/19 Golang