php 5.6 与之前版本不兼容中的数组属性定义辨析
2015-08-23 08:05
531 查看
在php5.6官方文档的不兼容页(http://php.net/manual/zh/migration56.incompatible.php)中提到了几个与以前版本不兼容的情况,其中提到了为类定义数组属性时,不兼容的情况,原文及示例如下:
在 PHP 5.6 之前的版本中,为类定义数组类型的属性时, 如果数组中同时使用了显式数组键和隐式数组键,并且显式的键和隐式的序列键相同, 那么数组的键将被覆盖。例如:
以上示例在PHP 5.5中输出:
在PHP 5.6中输出:
以上的例子,其实是非常特例的情况,其出现的前提条件有几条:
1. 必须是为类定义数组属性,并且是在类变量定义时初始化该属性的情况;
2. 一定是显式数组键在前,隐式数组键在后,隐式数组键对与自身位置相同的显示数组键的值的覆盖的情况;如果隐式数组键在前,显式数组键定义在后,则覆盖是一定会发生的,与版本无关;
3. 显式数组键必须是常量(包括类常量)方式,如果是字面量常量,则无论什么版本,在以上情况下,都不会出现隐式数组键覆盖显式数组键;
考察以下示例在PHP 5.5中的输出:
1.1 非类数组成员定义:
输出:
1.2 非初始化时赋值:
输出:
输出:
2. 显式键对隐式键的覆盖:
输出:
3. 字面量常量作为显式键名:
输出:
输出:
其实本质上,这是一个隐藏的很深的小bug。
在数组的定义中,如果有部分单元指定了数字键名,其后的隐式键名会延续此前最大数字(包括隐式或显式)键名,而不应产生隐式键名覆盖显式数字键名情况,无论显式键名是字面量常量还是符号常量。
见官方手册数组一节:http://php.net/manual/zh/language.types.array.php:
以上例程会输出:
只不过,5.6之前的版本在实现为类初始化数组成员时,用符号常量作数字键,对部分单元进行命名,出现了与数组语义定义不符的情况。
鉴于此种情况极其少见,故其影响较小,但一旦出现,则由此引起的bug极其难查。
在 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极其难查。
相关文章推荐
- Debatching(Splitting) XML Message in Orchestration using DefaultPipeline - BizTalk 2010
- zendframework配置流程
- 解决Mysql报错:PHP Warning: mysql_connect(): mysqlnd cannot connect to MySQL 4.1+ using the old insecure authentication.
- 如何理解ContentProvider?(通讯录)
- phpBB安装
- php 魔术方法 __call
- php 分页操作(三)
- PHP PDO 安全执行 set names utf8 的正确方法
- (3.1.2.1)getParameter()和getAttribute()
- php var_export与var_dump的区别
- MAC 系统升级10.10以后PHP验证码错误的解决办法。[ 一行代码轻松解决! ]
- php 分页操作(二)
- ubuntu 14.04 安装配置php7
- php 分页操作(一)
- Dsicuz x2.5去掉域名后面的/forum.php
- 如何用PHP通过拼接数据到显示在数据库图表上
- 关于php析构函数的一个有趣问题
- VTP(链路聚集协议)
- 利用PHPExcel将数据库数据导入excel表格的方法
- win7 访问ftp站点 不用浏览器显示