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 相关文章推荐
推荐Discuz!5的PHP代码高亮显示与实现可运行代码
Mar 15 PHP
利用discuz实现PHP大文件上传应用实例代码
Nov 14 PHP
PHP代码优化技巧小结
Sep 29 PHP
php生成图片验证码的方法
Apr 15 PHP
php版微信开发之接收消息,自动判断及回复相应消息的方法
Sep 23 PHP
PHP图片添加水印功能示例小结
Oct 03 PHP
thinkPHP实现多字段模糊匹配查询的方法
Dec 01 PHP
使用PHPStorm+XDebug搭建单步调试环境
Nov 19 PHP
php基于Redis消息队列实现的消息推送的方法
Nov 28 PHP
PHP递归的三种常用方式
Feb 28 PHP
PHP实现字母数字混合验证码功能
Jul 11 PHP
PHP新手指南
Apr 01 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与SQL注入攻击[三]
2007/04/17 PHP
通用PHP动态生成静态HTML网页的代码
2010/03/04 PHP
如何批量替换相对地址为绝对地址(利用bat批处理实现)
2013/05/27 PHP
php中使用url传递数组的方法
2015/02/11 PHP
PHP延迟静态绑定使用方法实例解析
2020/09/05 PHP
关于恒等于(===)和非恒等于(!==)
2007/08/20 Javascript
验证码在IE中不刷新而谷歌等浏览器正常的解决方案
2014/03/18 Javascript
jquery+ajax实现跨域请求的方法
2015/01/20 Javascript
JS实现兼容性好,自动置顶的淘宝悬浮工具栏效果
2015/09/18 Javascript
JS动态生成年份和月份实例代码
2017/02/04 Javascript
js控制文本框禁止输入特殊字符详解
2017/04/07 Javascript
js装饰设计模式学习心得
2018/02/17 Javascript
vue2.0 路由不显示router-view的解决方法
2018/03/06 Javascript
深入学习js函数的隐式参数 arguments 和 this
2019/06/24 Javascript
Python的Urllib库的基本使用教程
2015/04/30 Python
Python+django实现文件上传
2016/01/17 Python
Python解析json文件相关知识学习
2016/03/01 Python
python常见排序算法基础教程
2017/04/13 Python
python-opencv在有噪音的情况下提取图像的轮廓实例
2017/08/30 Python
python回调函数中使用多线程的方法
2017/12/25 Python
Python通过Pygame绘制移动的矩形实例代码
2018/01/03 Python
python实现雨滴下落到地面效果
2018/06/21 Python
python实现AES加密和解密
2019/03/27 Python
python实现批量nii文件转换为png图像
2019/07/18 Python
通过python扫描二维码/条形码并打印数据
2019/11/14 Python
Python字符串查找基本操作代码案例
2020/10/27 Python
一款纯css3实现的响应式导航
2014/10/31 HTML / CSS
中专生自荐信
2013/10/12 职场文书
中专生职业生涯规划书范文
2013/12/29 职场文书
应届毕业生求职信范文
2014/05/08 职场文书
公司联欢会策划方案
2014/05/19 职场文书
音乐学专业求职信
2014/07/22 职场文书
2015年见习期工作总结
2014/12/12 职场文书
元旦联欢晚会主持词
2015/07/01 职场文书
小程序后台PHP版本部署运行 LNMP+WNMP
2021/04/01 Servers
深入浅出的讲解:信号调制到底是如何实现的
2022/02/18 无线电