在php5.6官方文档的不兼容页(http://php.net/manual/zh/migration56.incompatible.php)中提到了几个与以前版本不兼容的情况,其中提到了为类定义数组属性时,不兼容的情况,原文及示例如下:

在 PHP 5.6 之前的版本中,为类定义数组类型的属性时, 如果数组中同时使用了显式数组键和隐式数组键,并且显式的键和隐式的序列键相同, 那么数组的键将被覆盖。例如:

 <?php
class C {
const ONE = 1;
public $array = [
self::ONE => 'foo',
'bar',
'quux',
];
} var_dump((new C)->array);
?>

以上示例在PHP 5.5中输出:

 array(2) {
[0]=>
string(3) "bar"
[1]=>
string(4) "quux"
}

在PHP 5.6中输出:

array(3) {
[1]=>
string(3) "foo"
[2]=>
string(3) "bar"
[3]=>
string(4) "quux"
}
以上的例子,其实是非常特例的情况,其出现的前提条件有几条:
1. 必须是为类定义数组属性,并且是在类变量定义时初始化该属性的情况;
2. 一定是显式数组键在前,隐式数组键在后,隐式数组键对与自身位置相同的显示数组键的值的覆盖的情况;如果隐式数组键在前,显式数组键定义在后,则覆盖是一定会发生的,与版本无关;
3. 显式数组键必须是常量(包括类常量)方式,如果是字面量常量,则无论什么版本,在以上情况下,都不会出现隐式数组键覆盖显式数组键;
考察以下示例在PHP 5.5中的输出:
1.1 非类数组成员定义:
 $array = [
ONE=>'foo',
'bar',
'quux'
];
var_dump($array);

输出:

array(3) {
[1] =>
string(3) "foo"
[2] =>
string(3) "bar"
[3] =>
string(4) "quux"
}

1.2 非初始化时赋值:

 define('ONE', 1);
class C {
public $array;
}
$c = new C;
$c->array = [ONE=>'foo','bar','quux'];
var_dump($c->array);

输出:

array(3) {
[1] =>
string(3) "foo"
[2] =>
string(3) "bar"
[3] =>
string(4) "quux"
}
 define('ONE', 1);
class C {
const ONE = 1;
public $array;
public function __construct() {
$this->array = array(
'bar',
ONE => 'foo',
'quux',
);
}
}
$c = new C;
var_dump($c->array);

输出:

array(3) {
[0] =>
string(3) "bar"
[1] =>
string(3) "foo"
[2] =>
string(4) "quux"
}

2. 显式键对隐式键的覆盖:

 define('ONE', 1);
class C {
const ONE = 1;
public $array = array(
'bar',
'quux',
ONE => 'foo',
'guru'
);
}
$c = new C;
var_dump((new C)->array);

输出:

array(3) {
[0] =>
string(3) "bar"
[1] =>
string(3) "foo"
[2] =>
string(4) "guru"
}

3. 字面量常量作为显式键名:

 class C {
public $array = array(
'bar',
'quux',
1 => 'foo',
'guru'
);
}
$c = new C;
var_dump((new C)->array);

输出:

array(3) {
[0] =>
string(3) "bar"
[1] =>
string(3) "foo"
[2] =>
string(4) "guru"
}
 class C {
public $array = array(
1 => 'foo',
'bar',
'quux',
);
}
$c = new C;
var_dump((new C)->array);

输出:

array(3) {
[1] =>
string(3) "foo"
[2] =>
string(3) "bar"
[3] =>
string(4) "quux"
}
其实本质上,这是一个隐藏的很深的小bug。
在数组的定义中,如果有部分单元指定了数字键名,其后的隐式键名会延续此前最大数字(包括隐式或显式)键名,而不应产生隐式键名覆盖显式数字键名情况,无论显式键名是字面量常量还是符号常量。
见官方手册数组一节:http://php.net/manual/zh/language.types.array.php:
 <?php
$array = array(
"a",
"b",
6 => "c",
"d",
);
var_dump($array);
?>

以上例程会输出:

array(4) {
[0]=>
string(1) "a"
[1]=>
string(1) "b"
[6]=>
string(1) "c"
[7]=>
string(1) "d"
}
只不过,5.6之前的版本在实现为类初始化数组成员时,用符号常量作数字键,对部分单元进行命名,出现了与数组语义定义不符的情况。
鉴于此种情况极其少见,故其影响较小,但一旦出现,则由此引起的bug极其难查。

php 5.6 与之前版本不兼容中的数组属性定义辨析的更多相关文章

  1. 解决Selenium与firefox浏览器版本不兼容问题

    因为在用java打开firefox浏览器的时候报错 org.openqa.selenium.firefox.NotConnectedException: Unable to connect to ho ...

  2. Selenium2学习-007-WebUI自动化实战实例-005-解决 Firefox 版本不兼容:org.openqa.selenium.WebDriverException: Failed to connect to binary FirefoxBinary

    此文主要讲述 Java 运行 Selenium 脚本时,因 Friefox 浏览器版本与 selenium-server-standalone-x.xx.x.jar 不兼容引起的 org.openqa ...

  3. cuda和gcc版本不兼容

    gcc8.1和cuda9.0版本不兼容,比较坑. 下面是各版本cuda支持的gcc: 从CUDA 4.1版本开始,现在支持gcc 4.5.gcc 4.6和4.7不受支持. 从CUDA 5.0版本开始, ...

  4. Gradle 'MYasprj' project refresh failed Error:CreateProcess error=216, 该版本的 %1 与您运行的 Windows 版本不兼容

    Gradle ‘MYasprj’ project refresh failed Error:CreateProcess error=216, 该版本的 %1 与您运行的 Windows 版本不兼容.请 ...

  5. 模块XXXX可能与您正在运行的Windows版本不兼容。检查该模块是否与regsvr32.exe的x86(32位)x64(64位)版本兼容。

    最近自己在编写ActiveX控件.遇到的麻烦事不少. 今天遇到了这个问题“模块XXXX可能与您正在运行的Windows版本不兼容.检查该模块是否与regsvr32.exe的x86(32位)x64(64 ...

  6. ubuntu下python安装pandas和numpy等依赖库版本不兼容的问题RuntimeWarning: numpy.dtype size changed

    习惯了linux下用pip install numpy及pip install pandas命令了.折腾了好久了. 上来先在python3中pip3 install numpy装了numpy,然后再p ...

  7. 【我的Android进阶之旅】解决 Error:CreateProcess error=216, 该版本的 %1 与您运行的 Windows 版本不兼容。请查看计算机的系统信息,了解是否需要 x86

    一.错误描述 刚刚打开Android Studio新建一个项目,然后就编译不了,报了如下所示的错误: 错误描述为: Error:CreateProcess error=216, 该版本的 %1 与您运 ...

  8. 解决selenium与firefox版本不兼容问题

    Python环境下类比 个人使用 32位环境 Python 2.7.12 Selenium 2.53.6 Firefox 47.01 安装selenium可用pip选择对应版本,参考另一教程. 因为在 ...

  9. idea2019版与maven3.6.2版本不兼容引发的血案

    昨天遇到了点问题解决浪费了一些时间(导致更新内容较少)回顾下问题 项目出现Unable to import maven project: See logs for details 翻了好多博客 莫名的 ...

随机推荐

  1. Spring MVC、MyBatis整合文件配置详解

    Spring:http://spring.io/docs MyBatis:http://mybatis.github.io/mybatis-3/ Building a RESTful Web Serv ...

  2. 关于&&和||

    从alert(1&&2)输出为2谈起 一.先来说说||(逻辑或),从字面上来说,只有前后都是false的时候才返回false,否则返回true. alert(true||false); ...

  3. 云计算与虚拟化KVM深度实践

    徐亮伟, 江湖人称标杆徐.多年互联网运维工作经验,曾负责过大规模集群架构自动化运维管理工作.擅长Web集群架构与自动化运维,曾负责国内某大型电商运维工作. 个人博客"徐亮伟架构师之路&quo ...

  4. TDataset.CopyFields

    Description Often when manipulating datasets with similar structures, you need to copy the records f ...

  5. (转存)面向切面编程(AOP)的理解

    面向切面编程(AOP)的理解 标签: aop编程 2010-06-14 20:17 45894人阅读 评论(11) 收藏 举报  分类: Spring(9)  在传统的编写业务逻辑处理代码时,我们通常 ...

  6. UGUI 事件穿透规则

    UGUI事件分为两大类:点击和拖拽. 点击包括 pointerdown, pointerup. 拖拽包括 begindrag, drag, enddrag. 点击事件无穿透:只会被最上层UI响应,不会 ...

  7. 前端开发之jQuery位置属性和筛选方法

    主要内容: 1.jQuery的位置属性及实例 (1)位置属性 (2)实例 --- 仿淘宝导航栏 2.jQuery的筛选方法及实例 (1)筛选方法 (2)实例一:嵌套选项卡 (3)实例二:小米官网滑动 ...

  8. centos7 安装 openvswitch

    1.安装依赖包:   yum -y install make gcc openssl-devel autoconf automake rpm-build redhat-rpm-config yum - ...

  9. 【bzoj3437】小P的牧场

    3437: 小P的牧场 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 947  Solved: 542[Submit][Status][Discuss ...

  10. for 续6

    ---------siwuxie095             for 实际运用样例(/f 的使用不列出来):     for %%i in (*) do echo %%i 显示当前目录下 ,所有非文 ...