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

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+的一些差异的更多相关文章

  1. 记 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 及 问题汇总 后来, ...

  2. php5.3到php7.0.x新特性介绍

    <?php /*php5.3*/ echo '<hr>'; const MYTT = 'aaa'; #print_r(get_defined_constants()); /* 5.4 ...

  3. Mac Pro 实现 PHP-5.6 与 PHP-7.0 等多版本切换

    先前参考 如何 实现PHP多版本的 共存 和 切换? 实现了Linux(Ubuntu/CentOS)系统下,PHP多版本的切换,但是在 Mac OS 下,由于用户权限控制的比较严格,文章里提到的脚本运 ...

  4. PHP5.6 和PHP7.0区别

    1. PHP7.0 比PHP5.6性能提升了两倍. 2.PHP7.0全面一致支持64位. 3.PHP7.0之前出现的致命错误,都改成了抛出异常. 4.增加了空结合操作符(??).效果相当于三元运算符. ...

  5. 升级lamp中php5.6到php7.0过程

    升级过程我就直接摘录博友,http://www.tangshuang.net/1765.html,几乎问题和解决办法都是参照他的,所以我也就不另外写了.谢谢!! 周末看了一下php7的一些情况,被其强 ...

  6. yum安装php5.5,php5.6和php7.0

    本文主要介绍在CentOS系统下的php多个版本的安装使用 1.清理系统上的旧版本php 1)查询已安装的php软件 rpm -qa|grep php* yum list installed | gr ...

  7. Ubuntu14.04下使用PPA安装php5.6,php7

    1.为了使用ppa(Personal Package Archives) 选安装依赖: # apt-get install python-software-properties 2.添加不同版本php ...

  8. wamp集成环境php多版本搭建(php5.5,php5.6,php7.0.6)

        首先需要搭建的版本可以在php官方(http://windows.php.net/download)下载对应的版本,X86对应的是32位操作系统,X64对应的是64位操作系统.    1:下载 ...

  9. php5.6.x到php7.0.x特性

    php5.6.x到php7.0.x特性 1.标量类型声明 字符串(string), 整数 (int), 浮点数 (float), 布尔值 (bool),callable,array,self,Clas ...

随机推荐

  1. InfluxDB 分布式时间序列数据库环境搭建——据qcon大会2016qiniu说集群很坑且闭源了

    InfluxDB 分布式时间序列数据库环境搭建   1. 环境说明 Ubuntu14.04  + influxDB V0.10.1 搭建3个节点的分布式数据库,副本数量2,各节点之间自动进行数据备份并 ...

  2. Spark SQL读parquet文件及保存

    import org.apache.spark.{SparkConf, SparkContext} import org.apache.spark.sql.{Row, SparkSession} im ...

  3. [Swift通天遁地]七、数据与安全-(2)对XML和HTML文档的快速解析

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  4. 虚拟机下安装VM

    Linux(CentOS 7)命令行模式安装VMware Tools 详解 [日期:2017-05-02] 来源:Linux社区  作者:Linux [字体:大 中 小] 本篇文章主要介绍了如何在Li ...

  5. 【转】linux之type命令

    转自: http://codingstandards.iteye.com/blog/831504 用途说明 type命令用来显示指定命令的类型.一个命令的类型可以是如下之一 alias 别名 keyw ...

  6. cocos2d-x 不规则碰撞检测 【转载】

    原文:http://www.2cto.com/kf/201401/272331.html //判断有没有点到有材质的部分, p_point相对, CCSprite坐标  (p_point是相对 Spr ...

  7. [Android]异常4-javax.mail.AuthenticationFailedException

    javax.mail.AuthenticationFailedException 背景:JavaMail发送电子邮件 异常原因: 可能一>发件人帐号.密码有误 可能二>需要使用SSL安全认 ...

  8. 《Java编程的逻辑》第三部分 泛型与容器

  9. php入门学习相关函数

      1.join(): 定义和用法 join() 函数返回由数组元素组合成的字符串. join() 函数是 implode() 函数的别名. 注释:join() 函数接受两种参数顺序.但是由于历史原因 ...

  10. 重绘DataGridView的DataGridViewCheckBoxCell控件

    最近项目中要用到在DataGridView单元格里面放置一个带有文本的 DataGridViewCheckBoxCell控件但原有 的是不支持的然后我就想着重写个 DataGridViewCheckB ...