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

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. MyReport报表系统v1.2公布

    经过多月奋战.MyReport报表系统最终完好,里程碑版本号V1.2隆重公布. 系统介绍 MyReport报表系统是基于MyReport报表引擎构建的报表开发工具平台产品.用户可以高速搭建报表中心,实 ...

  2. ubuntu rdesktop 全屏切换快捷键

    rdesktop 全屏之后进行切换 : ctrl + alt +enter

  3. 【转】关于使用Android6.0编译程序时,出现getSlotFromBufferLocked: unknown buffer: 0xac0f8650问题的解释

    这个问题是在测试leakCanaryTestDemo时发现的,期初看到有点蒙,这个demo中只使用了一个button和一个textView控件进行测试,按理说是不应该出现这种问题,在 网上查找这个问题 ...

  4. Versioning with the Override and New Keywords (C# Programming Guide)

    The C# language is designed so that versioning between base and derived classes in different librari ...

  5. Faas 典型场景——应用负载有显著的波峰波谷,典型用例-基于事件的数据处理

    Serverless适用的两大场景 场景一:应用负载有显著的波峰波谷 Serverless化与否的评判标准并不是公司规模的大小,而是其业务背后的具体技术问题,比如业务波峰波谷明显,如何实现削峰填谷.一 ...

  6. hdoj--1205--吃糖果(规律)

     吃糖果 Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total Sub ...

  7. 9.28NOIP模拟题

    9.28NOIP模拟题 题目 哈 哈哈 哈哈哈 英文题目与子目录名 ha haha hahaha 单个测试点时间限制 1秒 1秒 1秒 内存限制 256M 128M 64M 测试点数目 10 10 1 ...

  8. [Swift通天遁地]五、高级扩展-(9)颜色、设备、UserDefaults、URL等扩展方法

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

  9. max_allowed_packet设置问题

    最近在运行的项目出现了一个线上事故,有人反映商城的东西下不了单了,到后台看了一下,果然报了一个错 Cause: com.mysql.jdbc.PacketTooBigException: Packet ...

  10. Jmeter jdbc连接

    1.下载对应的驱动包(mysql-connector-java-5.1.13-bin.jar 可能现在有跟新的版本了),并放到Jmeter目录中的lib文件 2.打开Jmeter,添加JDBC Con ...