在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. 32位ubuntu14.04手动编译hadoop2.6.0

    下载官方编译好的包安装老是报错:Unable to load native-hadoop library for your platform 用file命令查看发现官方包里的libhadoop.so. ...

  2. httpclient pool帮助类

    摘自爬虫类  用于频繁请求减少网络消耗 import java.io.IOException; import java.io.InterruptedIOException; import java.i ...

  3. django 短链接改成长连接

    from django.conf import settings from django.core.wsgi import get_wsgi_application from gunicorn.app ...

  4. [代码]set容器查找操作使用

    对于set容器来说,查找功能是该容器的主要优势,故针对该容器查找功能作一测试. 主要有如下API接口: 测试源码如下: #include<set> void test(){ set< ...

  5. FireMoneky 画图 Point 赋值

    VCL 的 Canvas.Pen 对应FMX: Canvas.Stroke;VCL到 Canvas.Brush 对应FMX: Canvas.Fill. TCircle 圆形控件 Inkscape 0. ...

  6. 2013年最后的收成:avalon1.0正式发布

    大半年前我就说过,MVVM是前端究极的解决方案,因此之后我大多数时间都在折腾avalon,成立了专门的QQ群与感兴趣的一起讨论.感谢第一批吃螃蟹的人,avalon发展得很快,GITHUB上的贡献人数达 ...

  7. iOS开源项目:AFNetworking----写得非常好

    https://github.com/AFNetworking/AFNetworking 与asi-http-request功能类似的网络库,不过是基于NSURLConnection 和 NSOper ...

  8. win10如和设置远程桌面

    最近几天一直在搞远程桌面问题,电脑一直连不上远程,今天终于出来了. 前提前提  条件,要电脑允许Administrator用户,先把电脑切换到那个用户,然后进行下面操作. 1.在桌面,我的电脑图标,鼠 ...

  9. 使用net Manager工具配置远程连接oracle

    一,在服务端配置oracle端口在命令行中输入netca命令,打开相关配置默认端口号为1521 二,配置端口后使用Telnet工具调试端口是否联通 在命令行输入telnet 服务器ip 端口号 三,找 ...

  10. Debian Mount nfs 出错的解决

    系统未安装 nfs 客户端 #aptitude install nfs-common 解决!