PHP批斗大会之缺失的异常详解


Posted in PHP onJuly 09, 2019

故事的开始

这几天观察错误日志发现有一个数据反序列化的notice错误,实际情况我是从缓存中读取数据然后反序列化,因为反序列化失败,所以实际每次都是去数据库取的值。背后性能影响还是挺大的。

缺失的异常

刚开始写代码的时候一直不明白为什么要用异常,感觉if else就能搞定了,为什么还要多此一举,现在反而觉得 php 的异常太少。

对比两种序列化场景,一个是json,另一个是serialize。

json

在json encode/decode的时候,如果出现异常,可以通过json_last_error()来获取。

https://www.php.net/manual/en...

这样的设计只能说勉强够用,不太符合面向对象的套路。

serialize/unserialize

在使用自带的序列化和反序列化的时候,相比json的处理,则更加简单粗暴,没有函数能拿到最后的错误,只会通过自定义的error handler来接管,然后自己去做出一些相应的处理。

为什么要捕获异常

比如我的代码比较乱,有的 key 是 json 序列化,有的 key 是 serialize。我们可以将 key 分类。不能确保其他人配置的对应关系是对的,或者有的人忘记了,所以我需要用捕获异常的方式来兜底,这样我们的代码更加健壮一些。当unserialize失败之后,我们可以尝试去json_decode,而不是立即返回一个false,从而把请求传递到数据库。

代码演示

error_reporting(E_ALL);

$a = ["a" => 1];

class UnSerializeException extends ErrorException
{

}

set_error_handler(function ($severity, $message, $file, $line) {
  $info = explode(":", $message);

  if ($severity == E_NOTICE) {
    if ($info[0] == "unserialize()") {
      throw new UnSerializeException($message);
    }
    return true;
  } else {

    throw new ErrorException($message, 0, $severity, $file, $line);;
  }
});


try {
  $b = unserialize(json_encode($a));
} catch (ErrorException $exception) {
  var_dump(get_class($exception), $exception->getMessage(), $exception->getTraceAsString()); // 捕获到了
} finally {
  restore_error_handler();
}

try {
  $b = unserialize(json_encode($a));
} catch (ErrorException $exception) {
  var_dump(get_class($exception), $exception->getMessage(), $exception->getTraceAsString()); // 无法捕获
}

输出结果

string(20) "UnSerializeException"
string(43) "unserialize(): Error at offset 0 of 7 bytes"
string(181) "#0 [internal function]: {closure}(8, 'unserialize(): ...', '/Users/mengkang...', 34, Array)
#1 /Users/mengkang/PhpstormProjects/xxx/test.php(34): unserialize('{"a":1}')
#2 {main}"

Notice: unserialize(): Error at offset 0 of 7 bytes in /Users/mengkang/PhpstormProjects/xxx/test.php on line 42

后记

所以 php 代码的异常设计还是任重而道远的,而这些已经设定的“旧的规范”要推翻,需要“勇气”,毕竟会影响所有的使用者。

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

PHP 相关文章推荐
PHP的中问验证码
Nov 25 PHP
PHP 开源框架22个简单简介
Aug 24 PHP
php全局变量和类配合使用深刻理解
Jun 05 PHP
利用PHP将部分内容用星号替换
Apr 21 PHP
PHP常用的小程序代码段
Nov 14 PHP
Linux系统中设置多版本PHP共存配合Nginx服务器使用
Dec 21 PHP
功能强大的php文件上传类
Aug 29 PHP
php实现有序数组打印或排序的方法【附Python、C及Go语言实现代码】
Nov 10 PHP
PHP 7安装调试工具Xdebug扩展的方法教程
Jun 17 PHP
PHP对象的浅复制与深复制的实例详解
Oct 26 PHP
layui数据表格自定义每页条数limit设置
Oct 26 PHP
如何利用PHP实现上传图片功能详解
Sep 24 PHP
PHP结合Redis+MySQL实现冷热数据交换应用案例详解
Jul 09 #PHP
PHP+Redis开发的书签案例实战详解
Jul 09 #PHP
使用composer命令加载vendor中的第三方类库 的方法
Jul 09 #PHP
Laravel+Intervention实现上传图片功能示例
Jul 09 #PHP
Laravel框架实现多个视图共享相同数据的方法详解
Jul 09 #PHP
Laravel5.1框架注册中间件的三种场景详解
Jul 09 #PHP
PHP使用 Pear 进行安装和卸载包的方法详解
Jul 08 #PHP
You might like
PHP写MySQL数据 实现代码
2009/06/15 PHP
数组与类使用PHP的可变变量名需要的注意的问题
2013/06/20 PHP
AJAX的跨域访问-两种有效的解决方法介绍
2013/06/22 PHP
PHP实现将科学计数法转换为原始数字字符串的方法
2014/12/16 PHP
使用PHPStorm+XDebug搭建单步调试环境
2017/11/19 PHP
DWZ刷新dialog解决方法
2013/03/03 Javascript
JavaScript如何从listbox里同时删除多个项目
2013/10/12 Javascript
JavaScript获取网页支持表单字符集的方法
2015/04/02 Javascript
基于Node.js的强大爬虫 能直接发布抓取的文章哦
2016/01/10 Javascript
快速解决处理后台返回json数据格式的问题
2018/08/07 Javascript
详解vuex 渐进式教程实例代码
2018/11/27 Javascript
重学JS之显示强制类型转换详解
2019/06/30 Javascript
JS实现提示效果弹出及延迟隐藏的功能
2019/08/26 Javascript
解决Vue打包上线之后部分CSS不生效的问题
2019/11/12 Javascript
JS检索下拉列表框中被选项目的索引号(selectedIndex)
2019/12/17 Javascript
js 闭包深入理解与实例分析
2020/03/19 Javascript
小程序自定义弹框效果
2020/11/16 Javascript
[46:49]完美世界DOTA2联赛PWL S3 access vs Rebirth 第二场 12.19
2020/12/24 DOTA
Python 时间操作例子和时间格式化参数小结
2014/04/24 Python
wxPython窗口中文乱码解决方法
2014/10/11 Python
详解Python中for循环是如何工作的
2017/06/30 Python
wxPython实现带颜色的进度条
2019/11/19 Python
解决django 向mysql中写入中文字符出错的问题
2020/05/18 Python
HTML5 解析规则分析
2009/08/14 HTML / CSS
美国一站式电动和手动工具商店:International Tool
2020/11/26 全球购物
珍珠鸟教学反思
2014/02/01 职场文书
《植物妈妈有办法》教学反思
2014/02/25 职场文书
优秀广告词大全
2014/03/19 职场文书
党员创先争优承诺书
2014/03/26 职场文书
大学生创业计划书怎么写
2014/09/15 职场文书
党组织领导班子整改方案
2014/10/25 职场文书
淘宝文案策划岗位职责
2015/04/14 职场文书
学生犯错保证书
2015/05/09 职场文书
搞笑婚庆主持词
2015/06/29 职场文书
结婚主持人致辞
2015/07/28 职场文书
高中同学会致辞
2015/08/01 职场文书