一起搞懂PHP的错误和异常(二)
上回文章中我们讲到了错误是编译和语法运行时会出现的,它们与逻辑无关,是程序员在码代码时不应该出现的,也就是说,这些错误应该是尽量避免带到线上环境的,他们不能通过try...catch捕获到。而异常则正好相反。
什么是异常?
异常,指的是程序运行中出现的不符合预期的情况,通常允许它发生,并交由相应的异常处理来进行处理。当然,你也可以选择忽略掉异常的处理,但是就像严重错误一样,代码马上会终止运行。异常属于业务逻辑上的错误,基本上是我们人为的。
还是先通过一个简单的代码看下异常的抛出和捕获:
function test()
{
throw new Exception('This is test Error...');
}
try {
test();
} catch (Exception $e) {
print_r($e);
}
我们通过 throw 来抛出异常,然后在调用方法时将方法包裹在 try...catch 块中来捕获抛出的异常。这就是异常最基础的结构。
从这里我们可以看出,异常基本都是通过我们手动进行抛出的,让外部来进行处理。在PHP内部多数也是在类中会进行异常的抛出,这就是面向对象的错误处理思想了。比如说PDO类:
try {
// $pdo = new PDO(); // Fatal error: Uncaught ArgumentCountError: PDO::__construct() expects at least 1 parameter, 0 given
$pdo = new PDO('');
} catch (PDOException $e) {
print_r($e); // invalid data source name
}
注意上面那行注释的代码,没有传参数是错误,是无法捕获的。而传了的参数不对,就是异常了,在PDO类的源码中发现参数不对进行了抛出。交给上层代码也就是我们这些调用方来进行捕获。
接下来,我们看下自定义的异常类和finally语句块的使用。
自定义的异常类都会去继承 Exception 类,这个类可以看做是所有异常的基类。它的结构如下:
class Exception
{
protected $message = 'Unknown exception'; // 异常信息
private $string; // __toString cache
protected $code = 0; // 用户自定义异常代码
protected $file; // 发生异常的文件名
protected $line; // 发生异常的代码行号
private $trace; // backtrace
private $previous; // previous exception if nested exception
public function __construct($message = null, $code = 0, Exception $previous = null);
final private function __clone(); // 不能被复制,如果clone异常类将直接产生致命错误
final public function getMessage(); // 返回异常信息
final public function getCode(); // 返回异常代码
final public function getFile(); // 返回发生异常的文件名
final public function getLine(); // 返回发生异常的代码行号
final public function getTrace(); // backtrace() 数组
final public function getPrevious(); // 之前的 exception
final public function getTraceAsString(); // 已格成化成字符串的 getTrace() 信息
// Overrideable
public function __toString(); // 可输出的字符串
}
通过上述类定义,我们可以看出,我们能重写 构造函数 和 __toString() 方法,也能使用一些受保护的属性。那么我们就来定义一个自定义的异常类吧。
class TestException extends Exception
{
protected $code = 200;
public function __construct($message = null, $code = 0, Exception $previous = null){
$this->message = 'TestException:' . $message;
}
public function __toString(){
return 'code: ' . $this->code . '; ' . $this->message;
}
}
function test2()
{
throw new TestException('This is test2 Error...');
}
try {
test2();
} catch (TestException $e) {
echo $e, PHP_EOL; // code: 200; TestException:This is test2 Error...
}
还是非常好理解的吧,大部分的PHP框架都会有自定义异常的组件或者能力供我们使用,因为现代框架还是以面向对象为基础的,所以异常会定义的比较详细。不同组件会提供不同的异常类来进行异常的提示封装。
接下来就是 finally 关键字,其实这个并没有什么可多说的,finally 的特点就是不管有没有出现异常,都会去执行 finally 关键字所定义代码块内部的内容。
try {
test2();
} catch (TestException $e) {
echo $e, PHP_EOL;
} finally {
echo 'continue this code ...', PHP_EOL;
}
// code: 200; TestException:This is test2 Error...
// continue this code ...
说了这么多,最后我们来结合上述内容来处理下除0错误的异常抛出。在文章开头已经说过,错误是应该避免的,而异常是属于逻辑业务的。所以当我们接到一个需要做除法的参数时,可以先判断这个数是否为0,如果是0的话,就抛出异常让上层调用者来处理,如果不是0的话,就让它正常进行除法运算就好了。
function test3($d)
{
if ($d == 0) {
throw new Exception('除数不能为0');
}
return 1 / $d;
}
try {
echo test3(2), PHP_EOL;
} catch (Exception $e) {
echo 'Excepition:' . $e->getMessage(), PHP_EOL;
} finally {
echo 'finally:继续执行!', PHP_EOL;
}
// 0.5
// finally:继续执行!
try {
echo test3(0), PHP_EOL;
} catch (Exception $e) {
echo 'Excepition:' . $e->getMessage(), PHP_EOL;
} finally {
echo 'finally:继续执行!', PHP_EOL;
}
// Excepition:除数不能为0
// finally:继续执行!
总结
异常相关的使用就是这些了,通过这两篇文章,相信大家已经对PHP的错误和异常有了一些直观的了解了。接下来的文章我们将一起对比下错误和异常,并且说明一下PHP7对错误有了哪些改进。内容依然精彩,值得期待哦!!
参考文档:
https://www.cnblogs.com/init-007/p/11242813.html
https://www.php.net/manual/zh/language.exceptions.php
https://www.php.net/manual/zh/class.exception.php
https://www.php.net/manual/zh/language.exceptions.extending.php
一起搞懂PHP的错误和异常(二)的更多相关文章
- 一起搞懂PHP的错误和异常(一)
在PHP的学习过程中,我们会接触到两个概念,一个是错误,一个是异常.啥玩意?他们不是一个东西嘛?如果接触过Java.C#之类的纯面向对象语言的同学,可能对异常是没有什么问题,毕竟所有的问题都可以try ...
- 一起搞懂PHP的错误和异常(三)
关于错误与异常的最后一篇文章,我们来进行一些总结. PHP中错误和异常的区别 通过前面两篇文章的学习,我们来直接将错误和异常摆上来进行对比,看看他们的区别与联系: 错误的出现通常是语法或编译运行时错误 ...
- 不想再被鄙视?那就看进来! 一文搞懂Python2字符编码
程序员都自视清高,觉得自己是创造者,经常鄙视不太懂技术的产品或者QA.可悲的是,程序员之间也相互鄙视,程序员的鄙视链流传甚广,作为一个Python程序员,自然最关心的是下面这幅图啦 我们项目组一值使用 ...
- 一文搞懂所有Java集合面试题
Java集合 刚刚经历过秋招,看了大量的面经,顺便将常见的Java集合常考知识点总结了一下,并根据被问到的频率大致做了一个标注.一颗星表示知识点需要了解,被问到的频率不高,面试时起码能说个差不多.两颗 ...
- Java进阶专题(二十六) 将近2万字的Dubbo原理解析,彻底搞懂dubbo
前言 前面我们研究了RPC的原理,市面上有很多基于RPC思想实现的框架,比如有Dubbo.今天就从Dubbo的SPI机制.服务注册与发现源码及网络通信过程去深入剖析下Dubbo. Dubbo架构 ...
- 一文搞懂如何使用Node.js进行TCP网络通信
摘要: 网络是通信互联的基础,Node.js提供了net.http.dgram等模块,分别用来实现TCP.HTTP.UDP的通信,本文主要对使用Node.js的TCP通信部份进行实践记录. 本文分享自 ...
- 五分钟搞懂POM设计模式
转载请注明出处️ 作者:IT小学生蔡坨坨 原文链接:五分钟搞懂POM设计模式 大家好,我是IT小学生蔡坨坨. 今天,我们来聊聊Web UI自动化测试中的POM设计模式. 为什么要用POM设计模式 前期 ...
- WebAPI 用ExceptionFilterAttribute实现错误(异常)日志的记录(log4net做写库操作)
WebAPI 用ExceptionFilterAttribute实现错误(异常)日志的记录(log4net做写库操作) 好吧,还是那个社区APP,非管理系统,用户行为日志感觉不是很必要的,但是,错误日 ...
- 每个java初学者都应该搞懂的问题
对于这个系列里的问题,每个学JAVA的人都应该搞懂.当然,如果只是学JAVA玩玩就无所谓了.如果你认为自己已经超越初学者了,却不很懂这些问题,请将你自己重归初学者行列.内容均来自于CSDN的经典老贴. ...
随机推荐
- VIM正则表达式的懒惰模式
例如有如下一段话: Another whale sighting occurred on , <2004>. AK and HI 要匹配每一个<...>,如果用<.> ...
- GO语言的基本语法之变量,常量,条件语句,循环语句
GO语言的基本语法之变量,常量,条件语句,循环语句 作为慕课网得笔记自己看 定义变量: 使用var关键字 var a, b, C bool var s1, s2 string = "hell ...
- DVWA靶场之CSRF(跨站请求伪造)通关
Low: 服务器就看了password_new与password_conf是否相同,没有其他的验证 重新构造一个html页面,(自己假装自己是受害者,ip是靶场ip非本地ip) 1 <img s ...
- stm32 串口接收一次后再也无法接受,接受都为0
经检测为串口接受后进入别的程序,开辟了2048的临时数组,因为堆栈溢出.stm32总共堆栈为
- NOIP 模拟 $14\; \text{队长快跑}$
题解 \(by\;zj\varphi\) 一道很妙的 \(dp\) 题,方程状态不好设置,细节也不少 看到数据范围,直接想离散化 设 \(f_{i,j}\) 表示处理完前 \(i\) 个水晶,其中摧毁 ...
- kubebuilder实战之二:初次体验kubebuilder
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- C# wpf中关于binding的converter无效的情况
最近碰到bingding设置了convert转换无效的问题.困扰了我好久.这里记录分析一下. 先说下现象 我把TextBox的text属性 绑定到了对应的 convert.代码如下 希望吧pd_no ...
- wpf toggleSwitch 的只读属性
xml code --------------------------------------------- <Page x:Class="UWPDemo.MainPage" ...
- 一 MongoDB入门
一.MongoDB概念解析(对比MySQL学习): 举个例子: MongoDB可视化操作工具:推荐Robomongo 二.MongoDB默认的概念: 1.MongoDB的单个实例可以容纳多个独立的数据 ...
- 高性能利器:CDN我建议你好好学一下!
硬核干货分享,欢迎关注[Java补习课]成长的路上,我们一起前行 ! <高可用系列文章> 已收录在专栏,欢迎关注! CDN 概述 CDN 全称 Content Delivery Netwo ...