关于PHP数组Key的强制类型转换

关于PHP数组Key的强制类型转换

PHP是弱类型语言,就像JavaScript一样,在定义变量时,不需要强制指定变量的类型。同时,PHP又有着强大的数组功能,数组的Key即可以是普通的数字类型下标,也可以是字符串类型的Hash键值,那么,当一个数组的Key同时拥有字符串和数字时,会产生什么情况呢?

首先来看下面这样一段代码:

$arr = [
    "1" => "a",
    "01" => "b",
    1 => "aa",
    1.1 => "aaa",
    "0.1" => "bb",
];

var_dump($arr);

// array(3) {
//     [1] =>
//     string(3) "aaa"
//     '01' =>
//     string(1) "b"
//     '0.1' =>
//     string(2) "bb"
// }

咦?我们定义的"1"、1下标的值都变成了1.1的"aaa"了?

没错,PHP中的数组Key值只接受数字和字符串类型,当Key是字符串时,会强制转换为数字类型,遵守类型强制转换的规则。浮点数也是同样的道理,直接转换成了向下取整的整型。

那么"0.1"和"01"为什么还在?首先,"01"不是标准的十进制数值,无法转换成整型,所以"01"还是一个字符串下标,那"0.1"呢?它当然也不是一个标准的十进制数值。这里是违背了字符串转型数字的强制类型转换原则的,在变量的强制转换中,这两种字符串都会被转换为0,但在数组中则不会,这里会是一个坑,也是需要注意的地方。

在PHP官方文档中给出的Key值转换说明如下:

  • 包含有合法整型值的字符串会被转换为整型。例如键名 "8" 实际会被储存为 8。但是 "08" 则不会强制转换,因为其不是一个合法的十进制数值。
  • 浮点数也会被转换为整型,意味着其小数部分会被舍去。例如键名 8.7 实际会被储存为 8。
  • 布尔值也会被转换成整型。即键名 true 实际会被储存为 1 而键名 false 会被储存为 0。
  • Null 会被转换为空字符串,即键名 null 实际会被储存为 ""。
  • 数组和对象不能被用为键名。坚持这么做会导致警告:Illegal offset type。

接下来,是笔者曾经做过的一道面试题,和这个类型转换有着非常大的关系,代码如下:

$a      = ['a'];
$a[2]   = 'b';
$a[]    = 'c';
$a['1'] = 'd';

// 以下循环的输出结果是?
foreach ($a as $v) {
	echo $v, ',';
}

// 以下循环的输出结果是?
for ($i = 0; $i < count($a); ++$i) {
	echo $a[$i], '  ,';
}

大家先不要运行,直接看代码看看能不能看出这两段代码的输出结果会是什么,然后运行一下,看看结果和你想像的是不是一样。

测试代码: https://github.com/zhangyue0503/dev-blog/blob/master/php/201910/source/%E5%85%B3%E4%BA%8EPHP%E6%95%B0%E7%BB%84Key%E7%9A%84%E5%BC%BA%E5%88%B6%E8%BD%AC%E6%8D%A2.php

参考资料: https://www.php.net/manual/zh/language.types.array.php

本文分享自微信公众号 - 硬核项目经理(fullstackpm)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-11-11

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Rust语言学习交流

【Rust日报】 2019-10-26 filite:简单,轻巧且独立的 pastebin 文件共享服务

filite是一个简单,轻巧且独立的pastebin,URL shortener和文件共享服务,可以托管文件,重定向链接并存储文本。

7240
来自专栏渗透云笔记

后渗透之权限维护 整理

可以看一下对比,创建test用户,net user查看用户是可以看见的,而admin$,因为加了个$符号,用net user命令是看不见的。

10430
来自专栏学院君的专栏

Go 语言网络编程系列(三)—— HTTP 编程篇:客户端如何发起请求

通过前面介绍的 net.Dial 或 net.DialTimeout 函数来访问基于 HTTP 协议的网络服务是完全没有问题的,因为 HTTP 协议是基于 TC...

8420
来自专栏橙子探索测试

【安全测试】可怕的越权想法

大家提到安全测试会肃然起敬,之前看了一篇越权文章深受启发,于是就产生了下面的一系列想法,纯属个人观点,但不局限于此,如有更好想法的朋友,可留言自己观点。

4910
来自专栏Seebug漏洞平台

PHP-fpm 远程代码执行漏洞(CVE-2019-11043)分析

国外安全研究员 Andrew Danau在解决一道 CTF 题目时发现,向目标服务器 URL 发送 %0a 符号时,服务返回异常,疑似存在漏洞。

18030
来自专栏ChaMd5安全团队

【翻译】看我如何利用PHP的0day黑掉Pornhub并获得2W美刀奖励

在分析了Pornhub使用的平台之后,我们在其网站上检测到了unserialize函数的使用,其中的很多功能点(例如上传图片的地方等等)都受到了影响,例如下面两...

22140
来自专栏AI科技评论

如何利用并发性加速你的 python程序(上)

工程师 Jim Anderson 分享了他的经验,他写了一篇关于「通过并发性加快 python 程序的速度」的文章。Jim 有多年的编程经验,并且使用过各种编程...

9020
来自专栏云服务器web配置环境

云服务器web环境配置

腾讯云服务器是现在越来越多站长以及企业建站的首选了,因为腾讯云背靠腾讯这颗大树,有10亿微信用户和10亿QQ用户流量考验验做为背书,有足够的技术实力和奖金实力让...

26150
来自专栏云服务器部署步骤

腾讯云服务器部署步骤

我们使用 oneinstack 一键安装包进行安装,oneinstack的官网地址是:https://oneinstack.com/ 您可以在上面获取更多安装信...

25330
来自专栏Lauren的FPGA

Tcl的字符串操作:其他字符串操作命令

string命令提供了三种字符串裁剪方式:trim、trimleft和trimright。每种方式都需要两个参数,一个指定待裁剪的字符串,一个指定裁剪模式。默认...

9090

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励