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和ACCESS写聊天室(八)
Oct 09 PHP
php UTF-8、Unicode和BOM问题
May 18 PHP
php小偷相关截取函数备忘
Nov 28 PHP
php 5.3.5安装memcache注意事项小结
Apr 12 PHP
php实现用于删除整个目录的递归函数
Mar 16 PHP
php获取发送给用户的header信息的方法
Mar 16 PHP
PHP微信开发之微信消息自动回复下所遇到的坑
May 09 PHP
谈谈从phpinfo中能获取哪些值得注意的信息
Mar 28 PHP
PHP中的函数声明与使用详解
May 27 PHP
Laravel框架生命周期与原理分析
Jun 12 PHP
通过PHP设置BugFree获取邮箱通知
Apr 25 PHP
laravel实现于语言包的完美切换方法
Sep 29 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正则过滤html标签、空格、换行符的代码(附说明)
2010/10/25 PHP
php实现两个数组相加的方法
2015/02/17 PHP
Yii实现Command任务处理的方法详解
2016/07/14 PHP
php 根据自增id创建唯一编号类
2017/04/06 PHP
一些常用的JS功能函数(2009-06-04更新)
2009/06/04 Javascript
vue bootstrap小例子一枚
2017/06/09 Javascript
JavaScript中最常用的10种代码简写技巧总结
2017/06/28 Javascript
Vuex中mutations与actions的区别详解
2018/03/01 Javascript
vue :src 文件路径错误问题的解决方法
2018/05/15 Javascript
angular6.x中ngTemplateOutlet指令的使用示例
2018/08/09 Javascript
express中static中间件的具体使用方法
2019/10/17 Javascript
关于vue表单提交防双/多击的例子
2019/10/31 Javascript
JS实现基本的网页计算器功能示例
2020/01/16 Javascript
浅谈实现在线预览PDF的几种解决办法
2020/08/10 Javascript
Javascript节流函数throttle和防抖函数debounce
2020/12/03 Javascript
[04:10]DOTA2英雄梦之声_第11期_圣堂刺客
2014/06/21 DOTA
[02:27]2014DOTA2国际邀请赛 VG赛后采访:更大的挑战在等着我们
2014/07/13 DOTA
python网页请求urllib2模块简单封装代码
2014/02/07 Python
python多线程抓取天涯帖子内容示例
2014/04/03 Python
在Python中操作字典之setdefault()方法的使用
2015/05/21 Python
解决Python传递中文参数的问题
2015/08/04 Python
利用Python生成文件md5校验值函数的方法
2017/01/10 Python
Python实现扩展内置类型的方法分析
2017/10/16 Python
详解安装mitmproxy以及遇到的坑和简单用法
2019/01/21 Python
Django框架中间件(Middleware)用法实例分析
2019/05/24 Python
Python图像处理库PIL的ImageFilter模块使用介绍
2020/02/26 Python
Django封装交互接口代码
2020/07/12 Python
python使用建议与技巧分享(二)
2020/08/17 Python
python 实现简易的记事本
2020/11/30 Python
纯CSS3实现漂亮的input输入框动画样式库(Text input love)
2018/12/29 HTML / CSS
西安启天科技有限公司网络工程师面试题笔试题
2016/06/12 面试题
JAVA招聘远程笔试题
2015/07/23 面试题
整顿机关作风心得体会
2014/09/10 职场文书
thinkphp 获取控制器及控制器方法
2021/04/16 PHP
Java常用函数式接口总结
2021/06/29 Java/Android
Vue2.0搭建脚手架
2022/03/13 Vue.js