错误与异常

错误,可以理解程序本身的错误,例如语法错误。而异常则更偏向于程序运行不符合预期或者不符合正常流程;对于 PHP 语言而言,处理错误和处理异常使用的机制完全不同,因此很容易让人产生困惑。

例如,我们希望通过捕获异常来处理除数为 0 的情况,但是在捕获到异常之前,PHP 就触发了错误。

 try {
$a = 5 / 0;
} catch (Exception $e) {
$e->getMessage();
$a = -1; // 通过异常来处理 $a 为 0 的情况,但是实际上,捕获不到该异常
} echo $a;
// PHP Warning: Division by zero

也就是说,PHP 将除数为 0 的情况当成了错误而触发,而不会自动抛出异常,因此没法捕获。类似的,在很多情况下,PHP 都没办法自动抛出异常。只能通过 if - else 语句判断再结合 throw 方法来并手动抛出异常。

上述情况的发生,主要还是因为异常机制是 PHP 向面向对象演进后得到的产物。而在此之前 PHP 的报错主要还是通过错误机制,因此,在很多情况下,PHP 的错误要比异常更有价值。不过 PHP7 开始统一这两者,使错误也可以像异常那样抛出(这部分内容将放在异常部分讲解)。

错误级别

PHP 中的错误可理解为 使脚本不运行不正常的情况,根据错误级别从高到低可划分为五类

  1. Parse error 或 Syntax Error - 语法解析错误,触发该错误后,脚本完全无法运行;
  2. Fatal Error - 致命错误,触发该错误后,后面的脚本无法继续执行;
  3. Warning Error - 出现比较不恰当的地方,脚本可继续执行;
  4. Notice Error - 出现不恰当的地方,但是程度比 Warning Error 低,脚本可继续执行;
  5. Deprecated Error - 不推荐这么使用,未来可能会废弃,脚本可继续执行;

默认情况下,PHP 触发错误,并显示错误的级别及对应的提示。

Parse Error 示例 - 语句结尾不写分号

 echo "abc"
// PHP Parse error: syntax error, unexpected end of file, expecting ',' or ';

Fatal Error 示例 - 使用不存在的函数

 echo "before\n";
foo();
echo "after"; // 本行无法继续执行
// before
// PHP Fatal error: Uncaught Error: Call to undefined function foo()

Warning Error 示例 - 引入不存在的文件

 $a = "foo";
include('bar.php');
echo $a; // 程序继续执行
// PHP Warning: include(bar.php): failed to open stream: No such file or directory ...
// foo
Notice Error 示例 - 输出不存在的变量 echo $foo;
echo 12345;
// PHP Notice: Undefined variable: foo
// 12345

Deprecated Error 示例 - 在一些字符串函数中传入数字而非字符串

 strpos('12345', 3);
// PHP Deprecated: strpos(): Non-string needles will be interpreted as strings in the future

除了默认触发消息外,用户也可以使用 set_error_handler 函数自定义错误处理,大多数错误类型都可以进行自定义处理,除了 E_ERROR、 E_PARSE、 E_CORE_ERROR、 E_CORE_WARNING、 E_COMPILE_ERROR、 E_COMPILE_WARNING 外。

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

示例

 <?php
// E_ALL - 处理全部错误类型
set_error_handler('customError', E_ALL); /**
* @param int $errno 错误的级别
* @param string $errstr 错误的信息
* @param string $errfile 错误的文件名(可选)
* @param string $errline 错误发生的行号(可选)
*/
function customError(int $errno, string $errstr, string $errfile, string $errline)
{
echo sprintf('错误消息为 %s', $errstr);
} $a = 5 / 0; // 错误消息为 Division by zero

用户也可以通过 trigger_error 函数来手动触发一个用户级别的错误(E_USER_ERRORE_USER_WARNINGE_USER_NOTICEE_USER_DEPRECATED)。

 function division($a, $b) {
if($b == 0){
@trigger_error("0 不能作为除数", E_USER_NOTICE);
return -1;
}
return $a / $b;
} echo division(10, 0);

与错误有关的配置

一些错误处理相关的常用配置

  • error_reporting - 设置错误的报告级别
  • display_errors - 是否显示错误
  • display_startup_error - 是否显示 PHP 启动过程中的显示
  • log_errors - 设置是否将脚本运行的错误信息记录到服务器错误日志或者 error_log 之中

《Modern PHP》提出了四个规则

  1. 一定要让 PHP 报告错误;
  2. 在开发环境中要显示错误;
  3. 在生产环境中不能显示错误;
  4. 在开发环境和生产环境中都要记录错误;

开发环境推荐配置

 display_errors = On
display_startup_error = On
error_reporting = -1
log_errors = On

生产环境推荐配置

 display_errors = Off
display_startup_error = Off
; 报告 Notice 以外的所有错误
error_reporting = E_ALL & ~E_NOTICE
log_errors = On

Symfony 编码规范相关

异常和错误消息字符串必须使用 sprintf 来进行拼接;

throw new CommandNotFoundException(sprintf('Command "%s" does not exist.', $name));

当错误类型为 E_USER_DEPRECATED 时,需要添加 @

@trigger_error("foo", E_USER_DEPRECATED);

参考资料

PHP 核心特性 - 错误处理的更多相关文章

  1. Java Gradle入门指南之gretty插件(安装、命令与核心特性)

        Java Web应用开发时常使用Gradle来进行项目管理,可以十分便利地解决包依赖等问题.war插件的出现,让项目部署成为一个复制粘贴的过程,那有没有办法让Java web应用的部署,就像w ...

  2. ES6核心特性

    摘要:聊JS离不开ES6啊! 原文:ES6核心特性 作者:ljianshu 前言 ES6 虽提供了许多新特性,但我们实际工作中用到频率较高并不多,根据二八法则,我们应该用百分之八十的精力和时间,好好专 ...

  3. Mysql --09 Innodb核心特性——事务

    目录 Innodb核心特性--事务 1.什么是事务 2.事务的通俗理解 3.事务ACID特性 4.事务流程举例 5.事务的控制语句 6.事务隐式提交情况 7.事务日志redo基本功能 8.redo数据 ...

  4. 一篇文章带你搞懂 etcd 3.5 的核心特性

    作者 唐聪,腾讯云资深工程师,极客时间专栏<etcd实战课>作者,etcd活跃贡献者,主要负责腾讯云大规模k8s/etcd平台.有状态服务容器化.在离线混部等产品研发设计工作. etcd ...

  5. angularJS的核心特性

    前几天师傅让我了解一下angularJS,angularJS是一个前端框架,具体的优缺点和运用场景我现在也还没有搞清楚,暂时就先不做描述了,留到运用以后进行补充吧. angularJS四大核心特性:M ...

  6. 关于AngularJS学习整理---核心特性

    接触.学习AngularJS已经三个多月了,随着学习的深入,有些东西刚开始不明白,现在开始慢慢明白起来.于是,开始整理这几个月的学习成果.要不又要忘了...  初学Angular,是看到慕课网大漠穷秋 ...

  7. Angular四大核心特性

    Angular四大核心特性 Angular四大核心特性理论概述 MVC模式:它目的是为了分离视图.模型和控制器而设计出来的:其中数据模型用来储存数据,视图用来向用户展示应用程序,控制器充当模型和视图之 ...

  8. angular学习笔记(1)- 四大核心特性

    angular1学习笔记(1) -  angular1四大核心特性 1.MVC model:数据模型层 controller:业务逻辑和控制逻辑 view:视图层,负责展示 2.模块化 Module ...

  9. Zookeeper系列2 原生API 以及核心特性watcher

    原生API 增删改查询 public class ZkBaseTest { static final String CONNECT_ADDR = "192.168.0.120"; ...

随机推荐

  1. doGet()方法和doPost()方法有什么区别?

    1. 一般上,get是从服务器上获取数据,post是向服务器传送数据. 2. get是把参数数据队列加到提交表单的ACTION属性所指的URL中,值和表单内各个字段一一对应,在URL中可以看到.pos ...

  2. ubuntu远程桌面软件vnc。

    http://www.linuxidc.com/Linux/2017-03/141936.htm 现在Linux是非常火的  很多人喜欢用它,界面简单,操作容易,有很多图形化工具如WinSCP可以与U ...

  3. hdu 4725 The Shortest Path in Nya Graph (最短路+建图)

    The Shortest Path in Nya Graph Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K ...

  4. test-hellow world!

    //for C #include<stdio.h> int main() { printf("hellow world!"); return 0; } #for pyt ...

  5. Python面向对象-类、实例的绑定属性、绑定方法和__slots__

    绑定属性 从之前的文章中,我们知道python是动态语言——实例可以绑定任意属性. 那如果实例绑定的属性和类的属性名一样的话,会是什么情况呢? >>> class Student(o ...

  6. 百度大脑IOCR财会票据识别技术接入小程序,快速实现财会票据识别

    本文主要介绍iOCR财会票据识别的小程序功能实现. 想了解微信小程序的开发过程,请参看我之前的帖子:<UNIT接入小程序>https://ai.baidu.com/forum/topic/ ...

  7. AVProVideo 在android 真机使用经验分享

    AVProVideo 在 android 方面 如果想使用必须进行合理的设置:如图 发布的时候设置: 如果想使用代码替换播放视频: 第一步:设置  PlatformOptionsAndroid.ove ...

  8. SpringCloud路由网关Zuul

    一.什么是网关 Zuul的主要功能是路由转发和过滤器.路由功能是微服务的一部分,比如/api/user转发到到user服务,/api/shop转发到到shop服务.zuul默认和Ribbon结合实现了 ...

  9. 研究STM32F4的IEEE1558 PTP网络时间同步协议实现,软件是RL-TCPnet V7.X的底层

    这个东西发现挺有意思,刚开始研究没整明白怎么用,实测设置一次时间戳就可以使用了,后面在深入研究下 extern ARM_DRIVER_ETH_MAC Driver_ETH_MAC0; ARM_ETH_ ...

  10. JS reduce()方法详解,使用reduce数组去重

     壹 ❀ 引 稍微有了解JavaScript数组API的同学,对于reduce方法至少有过一面之缘,也许是for与forEach太强大,或者filter,find很实用,在实际开发中我至始至终没使用过 ...