PHP 核心特性 - 错误处理
错误与异常
错误,可以理解程序本身的错误,例如语法错误。而异常则更偏向于程序运行不符合预期或者不符合正常流程;对于 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 中的错误可理解为 使脚本不运行不正常的情况,根据错误级别从高到低可划分为五类
- Parse error 或 Syntax Error - 语法解析错误,触发该错误后,脚本完全无法运行;
- Fatal Error - 致命错误,触发该错误后,后面的脚本无法继续执行;
- Warning Error - 出现比较不恰当的地方,脚本可继续执行;
- Notice Error - 出现不恰当的地方,但是程度比 Warning Error 低,脚本可继续执行;
- 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_ERROR
、E_USER_WARNING
、E_USER_NOTICE
、E_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》提出了四个规则
- 一定要让 PHP 报告错误;
- 在开发环境中要显示错误;
- 在生产环境中不能显示错误;
- 在开发环境和生产环境中都要记录错误;
开发环境推荐配置
- 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 Errors: 4 Different Types (Warning, Parse, Fatal, and Notice Error)
- PHP: 预定义常量 - Manual
- PHP 核心技术与最佳实践 (豆瓣)
- PHP: 运行时配置 - Manual
- PHP 规范 - Symfony 代码规范 | PHP 技术论坛
- 很多PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里入手去提升,对此我整理了一些资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql优化、shell脚本、Docker、微服务、Nginx等多个知识点高级进阶干货需要的可以免费分享给大家,需要的加群(点击→)677079770
PHP 核心特性 - 错误处理的更多相关文章
- Java Gradle入门指南之gretty插件(安装、命令与核心特性)
Java Web应用开发时常使用Gradle来进行项目管理,可以十分便利地解决包依赖等问题.war插件的出现,让项目部署成为一个复制粘贴的过程,那有没有办法让Java web应用的部署,就像w ...
- ES6核心特性
摘要:聊JS离不开ES6啊! 原文:ES6核心特性 作者:ljianshu 前言 ES6 虽提供了许多新特性,但我们实际工作中用到频率较高并不多,根据二八法则,我们应该用百分之八十的精力和时间,好好专 ...
- Mysql --09 Innodb核心特性——事务
目录 Innodb核心特性--事务 1.什么是事务 2.事务的通俗理解 3.事务ACID特性 4.事务流程举例 5.事务的控制语句 6.事务隐式提交情况 7.事务日志redo基本功能 8.redo数据 ...
- 一篇文章带你搞懂 etcd 3.5 的核心特性
作者 唐聪,腾讯云资深工程师,极客时间专栏<etcd实战课>作者,etcd活跃贡献者,主要负责腾讯云大规模k8s/etcd平台.有状态服务容器化.在离线混部等产品研发设计工作. etcd ...
- angularJS的核心特性
前几天师傅让我了解一下angularJS,angularJS是一个前端框架,具体的优缺点和运用场景我现在也还没有搞清楚,暂时就先不做描述了,留到运用以后进行补充吧. angularJS四大核心特性:M ...
- 关于AngularJS学习整理---核心特性
接触.学习AngularJS已经三个多月了,随着学习的深入,有些东西刚开始不明白,现在开始慢慢明白起来.于是,开始整理这几个月的学习成果.要不又要忘了... 初学Angular,是看到慕课网大漠穷秋 ...
- Angular四大核心特性
Angular四大核心特性 Angular四大核心特性理论概述 MVC模式:它目的是为了分离视图.模型和控制器而设计出来的:其中数据模型用来储存数据,视图用来向用户展示应用程序,控制器充当模型和视图之 ...
- angular学习笔记(1)- 四大核心特性
angular1学习笔记(1) - angular1四大核心特性 1.MVC model:数据模型层 controller:业务逻辑和控制逻辑 view:视图层,负责展示 2.模块化 Module ...
- Zookeeper系列2 原生API 以及核心特性watcher
原生API 增删改查询 public class ZkBaseTest { static final String CONNECT_ADDR = "192.168.0.120"; ...
随机推荐
- ClassNotFoundException------我有一句妈卖批一定要讲
最近在写<Writing Compilers and Interpreters>一书的代码,本来打算用vim敲代码,一来每个字母都要自己敲,而来就当练习vim,但是感觉真是太不方便了,各种 ...
- [译]C# 7系列,Part 8: in Parameters in参数
原文:https://blogs.msdn.microsoft.com/mazhou/2018/01/08/c-7-series-part-8-in-parameters/ 背景 默认情况下,方法参数 ...
- IPFS学习-哈希
Hashes 哈希函数是接受一些任意输入并返回固定长度值的函数.具体值取决于所使用的给定哈希算法,例如SHA-1(GIT在使用),SHA-256,或者是BLAKE2,但是给予一个输入使用哈希算法总是返 ...
- C# 控制台输入和输出
目录 从控制台获取输入 将输出写入控制台 Console.Write() Console.WriteLine() 格式字符串 多重标记和值 格式化字符串 索引 对齐说明符 格式字段 标准数字格式说明符 ...
- 线程提供了一个方法:void join() ,join可以协调线程之间的同步运行。
package seday09; /** * @author xingsir * 线程提供了一个方法:void join() ,join可以协调线程之间的同步运行. * 此方法允许执行这个方法的线程在 ...
- Python爬虫实战:爬取腾讯视频的评论
前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: 易某某 PS:如有需要Python学习资料的小伙伴可以加点击下方链 ...
- NLP之语言模型
参考: https://mp.weixin.qq.com/s/NvwB9H71JUivFyL_Or_ENA http://yangminz.coding.me/blog/post/MinkolovRN ...
- strcmp函数和memcmp函数的用法区别及联系
前言: C语言中有很多东西容易搞混,最近笔者就遇到了一个问题.这里做个记录.就是memcmp和strcmp两者的用法,这里做个对比: 功能对比: A memcmp: 函数原型: int memcmp( ...
- js的动态表格的增删改查思路
1. 首先我们要知道,动态添加,肯定不是 在页面上写死得,而是通过js调用循环放入到页面上的,我们在写动态表格的时候不要先着急写,我们第一步要做的就是构思,要把自己的逻辑先弄清楚,不然的话,前面是好写 ...
- openwrt_在PPPOE上网的同时_访问光猫
openwrt_在PPPOE上网的同时_访问光猫 转载注明来源: 本文链接 来自osnosn的博客,写于 2019-11-14. 参考文章: 光猫桥接模式下,通过路由器访问光猫.简单设置 设置Open ...