当前位置: 首页 > news >正文

isset在php5.6-和php7.0+的一些差异

今天在公司实现一个模块功能时写了如下代码:

class ProductCategory
{
    const TYPES = [
        1 => 'type1',
        2 => 'type2',  
    ];
    
    public function getType()
    {
        return isset(self::TYPES[$this->type]) ? self:TYPES[$this->type] : 'unrecognized_type';
    }
}

居然报错, 在编译阶段就通不过了.

Fatal error: Cannot use isset() on the result of an expression (you can use "nul
l !== expression" instead)

错误信息意思很明显, 但我的代码isset里面并不是一个表达式啊,这让我百思不得其解.
我带着疑惑在家里重新敲下了如上代码,编译通过, 正常运行.
php -v查看版本, 7.1. 而公司的开发机上运行的是php5.6

那么,为什么会造成这样的差异呢?只能翻看源码看isset的底层实现.

众所周知, isset不是函数, 而是语法结构, 那么如果发生错误, 在编译阶段就会出错.

对比一下php5.6和php7.0+版本的zend_language_parse.y

在php5.6版本中的zend_language_parse.y的1283行

isset_variable:
        variable                { zend_do_isset_or_isempty(ZEND_ISSET, &$$, &$1 TSRMLS_CC); }
    |    expr_without_variable    { zend_error_noreturn(E_COMPILE_ERROR, "Cannot use isset() on the result of an expression (you can use \"null !== expression\" instead)"); }
;

很明显,在词法解析的时候, 类常量被定义成非变量了

看一看expr_without_variable的定义, 在该文件的776行到858行, 我们找到了这样一个定义:

    |    combined_scalar_offset { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); }

再看combined_scalar_offset 的定义:

general_constant '[' dim_offset ']' { zend_do_begin_variable_parse(TSRMLS_C); fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }

再看general_constant 的定义:

class_constant { $$ = $1; }

恍然大悟, 类常量被定义为非变量, 所以抛出编译错误.

而在php7.0+版本


combined_scalar_offset { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); }

是被去掉了的. 所以编译通过, 并成功运行.

也不知道这个算是bug, 还是5.6的feature~~~

相关文章:

  • Nginx支持WebSocket反向代理-学习小结
  • linux服务器安装anaconda,然后远程使用jupyter
  • ES6是什么
  • iOS设备、版本用户量统计
  • centos和pycharm中取绝对路径的差别
  • 在navicat中如何新建连接数据库
  • Unity VS 创建脚本自动添加头注释-时间-描述-作者等信息
  • django 自动化测试的故障排查
  • MySQL探秘(三):InnoDB的内存结构和特性
  • Java内存管理 -JVM 垃圾回收
  • POJ3259 SPFA判定负环
  • Qt5开发及实例学习
  • 深入BUG分析
  • HTML5的优缺点
  • 2018腾讯广告算法大赛总结/Rank7-复习代码
  • android 一些 utils
  • CentOS 7 防火墙操作
  • Docker 笔记(1):介绍、镜像、容器及其基本操作
  • ECS应用管理最佳实践
  • IndexedDB
  • iOS高仿微信项目、阴影圆角渐变色效果、卡片动画、波浪动画、路由框架等源码...
  • jquery ajax学习笔记
  • React-Native - 收藏集 - 掘金
  • React-redux的原理以及使用
  • select2 取值 遍历 设置默认值
  • Work@Alibaba 阿里巴巴的企业应用构建之路
  • 闭包,sync使用细节
  • 从输入URL到页面加载发生了什么
  • 基于axios的vue插件,让http请求更简单
  • 七牛云假注销小指南
  • 驱动程序原理
  • 如何用Ubuntu和Xen来设置Kubernetes?
  • 正则与JS中的正则
  • 积累各种好的链接
  • ​香农与信息论三大定律
  • # 数据结构
  • ###STL(标准模板库)
  • (Redis使用系列) Springboot 实现Redis消息的订阅与分布 四
  • (强烈推荐)移动端音视频从零到上手(下)
  • (顺序)容器的好伴侣 --- 容器适配器
  • (四) Graphivz 颜色选择
  • .NET3.5下用Lambda简化跨线程访问窗体控件,避免繁复的delegate,Invoke(转)
  • .NET委托:一个关于C#的睡前故事
  • @DataRedisTest测试redis从未如此丝滑
  • @media screen 针对不同移动设备
  • @serverendpoint注解_SpringBoot 使用WebSocket打造在线聊天室(基于注解)
  • [ 2222 ]http://e.eqxiu.com/s/wJMf15Ku
  • [Bada开发]初步入口函数介绍
  • [BZOJ] 3262: 陌上花开
  • [C#]扩展方法
  • [C]整形提升(转载)
  • [hdu 3652] B-number
  • [SharePoint][SharePoint Designer 入门经典]Chapter13 客户端Silverlight编程
  • [xsy2369]取名字
  • [代码]HTML页面如何接收外部参数