PHP 的错误机制也是非常复杂的,做了几年php,也没有仔细总结过,现在就补上这一课。

特别说明:文章的PHP版本使用5.5.32

PHP的错误级别

首先需要了解php有哪些错误。截至到php5.5,一共有16个错误级别

注意:尝试下面的代码的时候请确保打开error_log:

  1. error_reporting(E_ALL);
  2. ini_set('display_errors', 'On');

E_ERROR

这种错误是致命错误,会在页面显示Fatal Error, 当出现这种错误的时候,程序就无法继续执行下去了

错误示例:

  1. // Fatal error: Call to undefined function hpinfo() in /tmp/php/index.php on line 5
  2. hpinfo(); //E_ERROR

注意,如果有未被捕获的异常,也是会触发这个级别的。

  1. // Fatal error: Uncaught exception 'Exception' with message 'test exception' in /tmp/php/index.php:5 Stack trace: #0 {main} thrown in /tmp/php/index.php on line 5
  2. throw new Exception("test exception");

E_WARNING

这种错误只是警告,不会终止脚本,程序还会继续进行,显示的错误信息是Warning。比如include一个不存在的文件。

  1. //Warning: include(a.php): failed to open stream: No such file or directory in /tmp/php/index.php on line 7
  2. //Warning: include(): Failed opening 'a.php' for inclusion (include_path='.:/usr/share/pear:/usr/share/php') in /tmp/php/index.php on line 7
  3. include("a.php"); //E_WARNING

E_NOTICE

这种错误程度更为轻微一些,提示你这个地方不应该这么写。这个也是运行时错误,这个错误的代码可能在其他地方没有问题,只是在当前上下文情况下出现了问题。

比如$b变量不存在,我们把它赋值给另外一个变量

  1. //Notice: Undefined variable: b in /tmp/php/index.php on line 9
  2. $a = $b; //E_NOTICE

E_PARSE

这个错误是编译时候发生的,在编译期发现语法错误,不能进行语法分析。

比如下面的z没有设置为变量。

  1. // Parse error: syntax error, unexpected '=' in /tmp/php/index.php on line 20
  2. z=1; // E_PARSE

E_STRICT

这个错误是PHP5之后引入的,你的代码可以运行,但是不是PHP建议的写法。

比如在函数形参传递++符号

  1. // Strict Standards: Only variables should be passed by reference in /tmp/php/index.php on line 17
  2. function change (&$var) {
  3. $var += 10;
  4. }
  5. $var = 1;
  6. change(++$var);
  7. // E_STRICT

E_RECOVERABLE_ERROR

这个级别其实是ERROR级别的,但是它是期望被捕获的,如果没有被错误处理捕获,表现和E_ERROR是一样的。

经常出现在形参定义了类型,但调用的时候传入了错误类型。它的错误提醒也比E_ERROR的fatal error前面多了一个Catachable的字样。

  1. //Catchable fatal error: Argument 1 passed to testCall() must be an instance of A, instance of B given, called in /tmp/php/index.php on line 37 and defined in /tmp/php/index.php on line 33
  2. class A {
  3. }
  4. class B {
  5. }
  6. function testCall(A $a) {
  7. }
  8. $b = new B();
  9. testCall($b);

E_DEPRECATED

这个错误表示你用了一个旧版本的函数,而这个函数后期版本可能被禁用或者不维护了。

比如curl的CURLOPT_POSTFIELDS使用@FILENAME来上传文件的方法

  1. // Deprecated: curl_setopt(): The usage of the @filename API for file uploading is deprecated. Please use the CURLFile class instead in /tmp/php/index.php on line 42
  2. $ch = curl_init("http://www.remotesite.com/upload.php");
  3. curl_setopt($ch, CURLOPT_POSTFIELDS, array('fileupload' => '@'. "test"));

E_CORE_ERROR, E_CORE_WARNING

这两个错误是由PHP的引擎产生的,在PHP初始化过程中发生。

E_COMPILE_ERROR, E_COMPILE_WARNING

这两个错误是由PHP引擎产生的,在编译过程中发生。

E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE, E_USER_DEPRECATED,

这些错误都是用户制造的,使用trigger_error,这里就相当于一个口子给用户触发出各种错误类型。这个是一个很好逃避try catch异常的方式。

  1. trigger_error("Cannot divide by zero", E_USER_ERROR);
  2. // E_USER_ERROR
  3. // E_USER_WARING
  4. // E_USER_NOTICE
  5. // E_USER_DEPRECATED

E_ALL

E_STRICT出外的所有错误和警告信息。

错误控制

php中有很多配置和参数是可以控制错误,以及错误的日志显示的。第一步,我们需要了解的是php中的有关错误的配置有哪些?

我们按照php+php-fpm的模型来说,会影响php错误显示的其实是有两个配置文件,一个是php本身的配置文件php.ini,另外一个是php-fpm的配置文件,php-fpm.conf。

php.ini中的配置

  1. error_reporting = E_ALL // 报告错误级别,什么级别的
  2. error_log = /tmp/php_errors.log // php中的错误显示的日志位置
  3. display_errors = On // 是否把错误展示在输出上,这个输出可能是页面,也可能是stdout
  4. display_startup_errors = On // 是否把启动过程的错误信息显示在页面上,记得上面说的有几个Core类型的错误是启动时候发生的,这个就是控制这些错误是否显示页面的。
  5. log_errors = On // 是否要记录错误日志
  6. log_errors_max_len = 1024 // 错误日志的最大长度
  7. ignore_repeated_errors = Off // 是否忽略重复的错误
  8. track_errors = Off // 是否使用全局变量$php_errormsg来记录最后一个错误
  9. xmlrpc_errors = 0 //是否使用XML-RPC的错误信息格式记录错误
  10. xmlrpc_error_number = 0 // 用作 XML-RPC faultCode 元素的值。
  11. html_errors = On // 是否把输出中的函数等信息变为HTML链接
  12. docref_root = http://manual/en/ // 如果html_errors开启了,这个链接的根路径是什么
  13. fastcgi.logging = 0 // 是否把php错误抛出到fastcgi中

我们经常会被问到,error_reporting和display_errors有什么区别呢?这两个函数是完全不一样的。

PHP默认是会在日志和标准输出(如果是fpm模式标准输出就是页面)

error_reporting的参数是错误级别。表示什么样子的级别才应该触发错误。如果我们告诉PHP,所有错误级别都不需要触发错误,那么,不管是日志,还是页面,都不会显示这个错误,就相当于什么都没有发生。

display_errors是控制是否要在标准输出展示错误信息

log_errors则是控制是否要在日志中记录错误信息。

error_log是显示错误日志的位置,这个在php-fpm中往往会被重写,于是往往会发现的是cli和fpm的错误日志竟然不是在同一个文件中。

ignore_repeated_errors这个标记控制的是如果有重复的日志,那么就只会记录一条,比如下面的程序:

  1. error_reporting(E_ALL);
  2. ini_set('ignore_repeated_errors', 1);
  3. ini_set('ignore_repeated_source', 1);
  4. $a = $c; $a = $c; //E_NOTICE
  5. //Notice: Undefined variable: c in /tmp/php/index.php on line 20

本来会出现两次NOTICE的,但是现在,只会出现一次了…

track_errors开启会把最后一个错误信息存储到变量里面去,这个可能在对记日志的时候会有一些用处吧。不过我觉得真是没啥用…

html_errors 和 docref_root 两个是个挺有人性化的配置,配置了这两个参数以后,我们返回的错误信息中如果有一些在文档中有的信息,就会变成链接形式。

  1. error_reporting(E_ALL);
  2. ini_set('html_errors', 1);
  3. ini_set('docref_root', "https://secure.php.net/manual/zh/");
  4. include("a2.php"); //E_WARNING

能让你快速定位到我们出现错误的地方。是不是很人性~

php-fpm中的配置

  1. error_log = /var/log/php-fpm/error.log // php-fpm自身的日志
  2. log_level = notice // php-fpm自身的日志记录级别
  3. php_flag[display_errors] = off // 覆盖php.ini中的某个配置变量,可被程序中的ini_set覆盖
  4. php_value[display_errors] = off // 同php_flag
  5. php_admin_value[error_log] = /tmp/www-error.log // 覆盖php.ini中的某个配置变量,不可被程序中的ini_set覆盖
  6. php_admin_flag[log_errors] = on // 同php_admin_value
  7. catch_workers_output = yes // 是否抓取fpmworker的输出
  8. request_slowlog_timeout = 0 // 慢日志时长
  9. slowlog = /var/log/php-fpm/www-slow.log // 慢日志记录

php-fpm的配置中也有一个error_log配置,这个很经常会和php.ini中的error_log配置弄混。但他们记录的东西是不一样的,php-fpm的error_log只记录php-fpm本身的日志,比如fpm启动,关闭。

而php.ini中的error_log是记录php程序本身的错误日志。

那么在php-fpm中要覆盖php.ini中的error_log配置,就需要使用到下面几个函数:

  • php_flag
  • php_value
  • php_admin_flag
  • php_admin_value

这四个函数admin的两个函数说明这个变量设置完之后,不能在代码中使用ini_set把这个变量重新赋值了。而php_flag/value就仍然以php代码中的ini_set为准。

slowlog是fpm记录的,可以使用request_slowlog_timeout设置判断慢日志的时长。

总结

我们经常弄混的就是日志问题,以及某些级别的日志为何没有记录到日志中。最主要的是要看error_log,display_errors, log_errors这三个配置,只是在看配置的时候,我们还要注意区分php.ini里面的配置是什么,php-fpm.ini里面的配置是什么。

好吧,我觉得弄懂这些配置,基本就没有php日志记录不了的WTF的问题了。

作者:佚名

来源:51CTO

关于PHP的错误机制总结相关推荐

  1. 4,fail-fast错误机制

    一,fail-fast简介 在JDK的Collection中我们时常会看到类似于这样的话: ArrayList 注意,迭代器的快速失败行为无法得到保证,因为一般来说,不可能对是否出现不同步并发修改做出 ...

  2. PHP的错误机制总结

    PHP的错误机制也是非常复杂的,做了几年php,也没有仔细总结过,现在就补上这一课. 特别说明:文章的PHP版本使用5.5.32 PHP的错误级别 首先需要了解php有哪些错误.截至到php5.5,一 ...

  3. ABP+AdminLTE+Bootstrap Table权限管理系统第八节--ABP错误机制及AbpSession相关

      返回总目录:ABP+AdminLTE+Bootstrap Table权限管理系统一期 上一节我们讲到登录逻辑,我做的登录逻辑很简单的,我们来看一下abp module-zero里面的登录代码. # ...

  4. Nand Flash结构及错误机制

    Nand Flash是一种非易失性存储器,具有读写速度快.功耗低.存储密度高等优点,目前被广泛应用于电子产品中,如固态硬盘( SSD).手机.数码相机等.进入21世纪以来,随着CPU主频以及IO频率的 ...

  5. sqlserver 中事务与错误机制的处理

    成功返回1并提交事务,错误返回0并回滚事务 BEGIN try   begin tran   --其中userName为varchar类型,数据库中该字段存在不为int类型的数据,必然导致错误   u ...

  6. 百度二级域名批量绑定软件,绕过验证码错误机制

    前面的文章已经做了一个二级域名绑定exe软件,感觉再加个ui界面也许会好看点,操作更方便.此次除了UI界面的设计,还加入了二级域名备案和文件验证方式. 如果手动过旋转后,可能会出现一下的信息,即使旋转 ...

  7. undo系列学习之读一致性(ORA-01555错误机制分析)

    oracle在读的过程中,数据是静止的,没有脏读,也就是,未提交的永远都不会被读到.我们可以理解为,oracle在读的开始时,提前为他今后所要读的内容拍了一张"照片",把所有内容全 ...

  8. ASP.NET的错误处理机制

    通常情况下,我们在写ASP.NET程序的时候,会经常遇到如何处理错误处理机制的问题.可以说一个良好的错误处理机制是衡量Web应用程序好坏的一个重要标准. 下面将介绍四中错误处理机制: 1.使用Web. ...

  9. QTP3种错误处理机制

    QTP 拥有3种不同的错误处理机制: 1.场景恢复机制 2.VBS的Error 对象 3.缺省的错误处理[Settings 里的runonError选项所指定的设置] 它们的优先级分别是: 1.场景恢 ...

最新文章

  1. Jetson Nano and VIM3硬件参数对比及目标检测性能对比
  2. TensorFlow2-神经网络训练
  3. 浅析STM32之usbh_def.H
  4. linux svn可视化工具,CentOS6.5安装SVN 可视化管理工具iF.SVNAdmin
  5. Spring Boot Java应用代码混淆介绍
  6. char赋值字符串常量和数值的区别
  7. Python 数据结构与算法 —— 插入排序
  8. Java获取计算机各类信息的方法(磁盘,系统,内存等等信息)
  9. C3927 “->“: 非函数声明符后不允许尾随返回类型等错误
  10. 一个基于QT的开源串口调试工具
  11. Android 10.0 PackageManagerService(四)APK安装流程-[Android取经之路]
  12. 网上图片的几种保存方法
  13. java减号的正则_java 正则匹配 特殊字符 减号- 的情况,处理方式
  14. nodejs websocket 聊天应用
  15. 什么牌子的护眼灯对眼睛好?性价比最高的护眼灯
  16. hbuilder发生了错误请参阅日志文件1545838571032
  17. 安装配置Tomcat6教程
  18. Linux安装和使用Trickle的方法
  19. wireless tools工具的移植和使用
  20. Linux系统Shell if语句用法小结

热门文章

  1. 51单片机学习笔记(清翔版)(13)——LED点阵、74HC595
  2. 【Docker】Segmentation Fault or Critical Error encountered. Dumping core and abort
  3. Redis进阶实践之十八 使用管道模式提高Redis查询的速度
  4. Spring MVC重定向和转发
  5. 【javascript实现的图片查看器】仿lightbox
  6. 转:70个漂亮实用的JavaScript和Ajax技术(有图有例子)
  7. Web Application Security 网络应用程序安全 - (二)2010年网络安全威胁排行榜TOP 10...
  8. Struts2中UI标签之表单标签介绍
  9. JS身份证合法性校验完全版
  10. mysql分布式数据库架构_MySQL分布式数据库架构:分库、分表、排序、分页、分组、实现教程...