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~~~
原文地址:https://segmentfault.com/a/1190000016097997
isset在php5.6-和php7.0+的一些差异的更多相关文章
- 记 Mac Pro 系统升级后,编译安装 PHP-5.6.28 / PHP-7.0 报错修复过程
买 Mac Pro 的时候,系统为 OS X 10.11.5,编译 PHP-5.6.21 的时候,也遇到一些坑,安装过程记录如下: Mac Pro 编译安装 PHP 5.6.21 及 问题汇总 后来, ...
- php5.3到php7.0.x新特性介绍
<?php /*php5.3*/ echo '<hr>'; const MYTT = 'aaa'; #print_r(get_defined_constants()); /* 5.4 ...
- Mac Pro 实现 PHP-5.6 与 PHP-7.0 等多版本切换
先前参考 如何 实现PHP多版本的 共存 和 切换? 实现了Linux(Ubuntu/CentOS)系统下,PHP多版本的切换,但是在 Mac OS 下,由于用户权限控制的比较严格,文章里提到的脚本运 ...
- PHP5.6 和PHP7.0区别
1. PHP7.0 比PHP5.6性能提升了两倍. 2.PHP7.0全面一致支持64位. 3.PHP7.0之前出现的致命错误,都改成了抛出异常. 4.增加了空结合操作符(??).效果相当于三元运算符. ...
- 升级lamp中php5.6到php7.0过程
升级过程我就直接摘录博友,http://www.tangshuang.net/1765.html,几乎问题和解决办法都是参照他的,所以我也就不另外写了.谢谢!! 周末看了一下php7的一些情况,被其强 ...
- yum安装php5.5,php5.6和php7.0
本文主要介绍在CentOS系统下的php多个版本的安装使用 1.清理系统上的旧版本php 1)查询已安装的php软件 rpm -qa|grep php* yum list installed | gr ...
- Ubuntu14.04下使用PPA安装php5.6,php7
1.为了使用ppa(Personal Package Archives) 选安装依赖: # apt-get install python-software-properties 2.添加不同版本php ...
- wamp集成环境php多版本搭建(php5.5,php5.6,php7.0.6)
首先需要搭建的版本可以在php官方(http://windows.php.net/download)下载对应的版本,X86对应的是32位操作系统,X64对应的是64位操作系统. 1:下载 ...
- php5.6.x到php7.0.x特性
php5.6.x到php7.0.x特性 1.标量类型声明 字符串(string), 整数 (int), 浮点数 (float), 布尔值 (bool),callable,array,self,Clas ...
随机推荐
- CAGradientLayer功能
一.CAGradientLayer介绍 .CAGradientLayer是用于处理渐变色的层结构 .CAGradientLayer的渐变色能够做隐式动画 .大部分情况下.CAGradientLayer ...
- ListView布局之View复用原理举例
1.简单介绍: ListView是android开发中经常使用的控件,系统自带的那些样式,我就不列举了. 今天主要看一下.一个模仿系统历史通话记录的ListView. 效果例如以下: 上面ListVi ...
- [linux环境配置]个人用持续更新ing~
alias ll='ls -la' export PATH=$PATH:~/Desktop/myscript alias gpush='git push origin HEAD:refs/for/ma ...
- 特征变化--->特征向量中部分特征到类别索引的转换(VectorIndexer)
VectorIndexer: 倘若所有特征都已经被组织在一个向量中,又想对其中某些单个分量进行处理时,Spark ML提供了VectorIndexer类来解决向量数据集中的类别性特征转换. 通过为其提 ...
- Linux扩展正则表达式
1. 扩展正则表达式 1.1 +(加号) + 表示前一个字符出现1次或1次以上 1.1.1 理解+ 要求:取出文件内容连续出现的小写字母 [root@oldboyedu50-lnb /oldboy]# ...
- 巴什博弈----hdu2147-----较难
kiki's game Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 40000/10000 K (Java/Others)Total ...
- 数据清洗——python定位csv中的特定字符位置
之前发过一篇关于定位csv中的特殊字符的,主要是用到了python的自带的函数,近期又遇到了一些新的问题,比如isdigit()的缺点在于不能判断浮点型,以及小数中有多个小数点的情况.发现还是正则表达 ...
- 关于BUG
1.BUG的理解 2.提高BUG report的技巧
- RabbitMQ~说说Exchange的几种模式
RabbitMQ里的Exchange提供了四种模式,或者叫它类型,它们是fanout,direct,topic和header,其中前三种模式我们用的比较多,所有我们主要介绍前3种! Direct 任何 ...
- java 任意时间转换日期类型
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd"); try { Date dd=sdf.parse("201 ...