PHP的全局错误处理详解


Posted in PHP onApril 25, 2016

本文目的

PHP的全局错误处理,在开发项目的时候很有用,可以帮助开发者快速定位一些问题,提高工作效率。默认情况下,全局错误会直接输出,但是最近开发时使用的一个框架库对全局错误处理进行了设定,导致很多错误信息没有输出,在定位问题上有一定的耗时。所以,研究了一下此库的实现,发现它设定了error_reporting和set_error_handler,导致此现象。现在记录一下这两个函数的用法,作为备忘录。

背景

PHP没有类型检测,开发人员比较容易输入错误单词,引起致命错误,最终导致脚本停止执行。如果这个时候,没有得到任何错误消息,那么会是一件很痛苦的事情。你不得不从脚本的第一行代码开始调试,在成千上万行的代码中不断的print或者echo,直到定位到这个输错的单词。然后,有不得不原路返回,将先前添加的print或echo全部删除。这时一件及其枯燥乏味的工作。

一般情况

正常情况下,php会将致命错误直接输出,会将错误的出处(文件地址,行号)和原因等输出,这样,开发着可以很方便的定位到问题。

但是有些时候,可能由于php.ini的设置问题,可能是第三方框架配置的问题,导致这些信息没有输出,那么此时,必须学会自己设置相关参数,输出这些错误信息,帮助快速定位问题。

error_reporting

error_reporting是一个php的全局配置参数,在php.ini中。用于配置错误输出级别,参数是比特位,可以用来设置错误输出的级别,下面是从php.ini中copy出来的信息:

; error_reporting is a bit-field. Or each number up to get desired error
; reporting level
; E_ALL - All errors and warnings (doesn't include E_STRICT)
; E_ERROR - fatal run-time errors
; E_RECOVERABLE_ERROR - almost fatal run-time errors
; E_WARNING - run-time warnings (non-fatal errors)
; E_PARSE - compile-time parse errors
; E_NOTICE - run-time notices (these are warnings which often result
; from a bug in your code, but it's possible that it was
; intentional (e.g., using an uninitialized variable and
; relying on the fact it's automatically initialized to an
; empty string)
; E_STRICT - run-time notices, enable to have PHP suggest changes
; to your code which will ensure the best interoperability
; and forward compatibility of your code
; E_CORE_ERROR - fatal errors that occur during PHP's initial startup
; E_CORE_WARNING - warnings (non-fatal errors) that occur during PHP's
; initial startup
; E_COMPILE_ERROR - fatal compile-time errors
; E_COMPILE_WARNING - compile-time warnings (non-fatal errors)
; E_USER_ERROR - user-generated error message
; E_USER_WARNING - user-generated warning message
; E_USER_NOTICE - user-generated notice message
;
; Examples:
;
; - Show all errors, except for notices and coding standards warnings
;
;error_reporting = E_ALL & ~E_NOTICE
;
; - Show all errors, except for notices
;
;error_reporting = E_ALL & ~E_NOTICE | E_STRICT
;
; - Show only errors
;
;error_reporting = E_COMPILE_ERROR|E_RECOVERABLE_ERROR|E_ERROR|E_CORE_ERROR
;
; - Show all errors except for notices and coding standards warnings
;
error_reporting = E_ALL & ~E_NOTICE

默认情况下,php会输出所有错误信息,除了notice。同样,php标准函数中提供了名称相同的函数error_reporting(int $level),用于在php脚本中,完成同样的功能。这样将不会影响其他程序。值得注意的是,$level为0的时候是关闭错误输出,也就是任何错误都不会输出。

set_error_handler

php的默认错误处理是将消息输出。但是,有时候需要定义一些其他操作,这时就需要自定义错误处理函数。php提供内置函数set_error_handler可以帮助我们注册自己的错误处理函数。函数原型如下:

mixed set_error_handler ( callback $error_handler [, int $error_types = E_ALL | E_STRICT ] )

值得注意的是,即使注册了错误处理函数,默认的行为仍然会执行,也就是错误出现时,仍然会输出错误信息,所以需要在程序中显示的将错误级别设置为0,然后在注册自己的的错误处理函数。这种方式,在生产环境下,尤其重要,因为即时出错,敏感内部错误信息也不会暴露给潜在的恶意用户。还有很重要的一点需要指出,自定义错误处理函数不能处理fatal error(比如编译错误)。下面是一个使用自定义错误处理函数的列子:

<?php
error_reporting (0);
function error_handler ($error_level, $error_message, $file, $line) {
  $EXIT = FALSE;
  switch ($error_level) {
    case E_NOTICE:
    case E_USER_NOTICE:
      $error_type = 'Notice';
      break;
    case E_WARNING:
    case E_USER_WARNING:
      $error_type = 'Warning';
      break;
    case E_ERROR:
    case E_USER_ERROR:
      $error_type = 'Fatal Error';
      $EXIT = TRUE;
      break;
    default:
      $error_type = 'Unknown';
      $EXIT = TRUE;
      break;
  }
  printf ("%s: %s in %s on line %d\n", $error_type, $error_message, $file, $line);
 
  if ($EXIT) {
    die();
  }
}
set_error_handler ('error_handler');
 
//new NonExist();
echo $novar;
echo 3/0;
trigger_error ('Trigger a fatal error', E_USER_ERROR);
new NonExist();
?>

执行此脚本可以得到下面的输出:

Notice: Undefined variable: novar in /your/php_demo_file.php on line 40

Warning: Division by zero in /your/php_demo_file.php on line 41

Fatal Error: Trigger a fatal error in /your/php_demo_file.php on line 42

可以看到,最后的“new NoExistClass()”的异常,没有被自定义的错误处理函数捕获。

最后,捎带提一下,set_exception_handler注册顶层的异常处理,在web一用中,可以设定一下,然后统一的跳转到错误处理页面。

PHP 相关文章推荐
php 需要掌握的东西 不做浮躁的人
Dec 28 PHP
PHP合并数组+与array_merge的区别分析
Aug 01 PHP
php入门学习知识点四 PHP正则表达式基本应用
Jul 14 PHP
php数组函数序列 之shuffle()和array_rand() 随机函数使用介绍
Oct 29 PHP
PHP求小于1000的所有水仙花数的代码
Jan 10 PHP
PHP常用技巧总结(附函数代码)
Feb 04 PHP
php 调试利器debug_print_backtrace()
Jul 23 PHP
PHP UTF8中文字符截断函数代码
Sep 11 PHP
那些年我们错过的魔术方法(Magic Methods)
Jan 14 PHP
phpExcel中文帮助手册之常用功能指南
Aug 18 PHP
phpcms手机内容页面添加上一篇和下一篇
Jun 05 PHP
PHP中使用CURL发送get/post请求上传图片批处理功能
Oct 15 PHP
PHP预定义变量9大超全局数组用法详解
Apr 23 #PHP
php构造函数与析构函数
Apr 23 #PHP
浅谈PHP中的
Apr 23 #PHP
简单谈谈PHP中的include、include_once、require以及require_once语句
Apr 23 #PHP
浅析Yii2 gridview实现批量删除教程
Apr 22 #PHP
浅析Yii2 GridView 日期格式化并实现日期可搜索教程
Apr 22 #PHP
浅析Yii2 GridView实现下拉搜索教程
Apr 22 #PHP
You might like
邮箱正则表达式实现代码(针对php)
2013/06/21 PHP
学习php设计模式 php实现访问者模式(Visitor)
2015/12/07 PHP
PHP图形操作之Jpgraph学习笔记
2015/12/25 PHP
模仿JQuery sortable效果 代码有错但值得看看
2009/11/05 Javascript
理解Javascript_15_作用域分配与变量访问规则,再送个闭包
2010/10/20 Javascript
Jsonp 跨域的原理以及Jquery的解决方案
2011/06/27 Javascript
JS小功能(button选择颜色)简单实例
2013/11/29 Javascript
js键盘上下左右键怎么触发function(实例讲解)
2013/12/14 Javascript
jQuery中delegate()方法用法实例
2015/01/19 Javascript
jQuery自动添加表单项的方法
2015/07/13 Javascript
微信小程序  modal弹框组件详解
2016/10/27 Javascript
js实现砖头在页面拖拉效果
2020/11/20 Javascript
javascript设计模式之单体模式学习笔记
2017/02/15 Javascript
微信小程序实现手势图案锁屏功能
2018/01/30 Javascript
详解NodeJs开发微信公众号
2018/05/25 NodeJs
Vue 路由 过渡动效 数据获取方法
2018/07/31 Javascript
vue自定义全局共用函数详解
2018/09/18 Javascript
微信小程序获取位置展示地图并标注信息的实例代码
2019/09/01 Javascript
node.js express捕获全局异常的三种方法实例分析
2019/12/27 Javascript
[45:59]完美世界DOTA2联赛PWL S2 FTD vs GXR 第二场 11.22
2020/11/24 DOTA
python3音乐播放器简单实现代码
2020/04/20 Python
Python控制多进程与多线程并发数总结
2016/10/26 Python
pygame实现烟雨蒙蒙下彩虹雨
2019/11/11 Python
python 实现图片上传接口开发 并生成可以访问的图片url
2019/12/18 Python
Python3列表List入门知识附实例
2020/02/09 Python
Windows下pycharm安装第三方库失败(通用解决方案)
2020/09/17 Python
python之openpyxl模块的安装和基本用法(excel管理)
2021/02/03 Python
英国女性化妆品收纳和家具网站:Beautify
2019/12/07 全球购物
俄罗斯天然和有机产品、健康生活网上商店:Fitomarket.ru
2020/10/09 全球购物
Jar包的作用是什么
2014/03/30 面试题
班主任新年寄语
2014/04/04 职场文书
婚前协议书
2014/04/15 职场文书
司法建议书范文
2014/05/13 职场文书
中层干部培训方案
2014/06/16 职场文书
先进班集体事迹材料
2014/12/25 职场文书
中学生逃课检讨书
2015/02/17 职场文书