PHP数组Key强制类型转换实现原理解析


Posted in PHP onSeptember 01, 2020

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/关于PHP数组Key的强制转换.php

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
PHP个人网站架设连环讲(一)
Oct 09 PHP
PHP 七大优势分析
Jun 23 PHP
基于php split()函数的用法详解
Jun 05 PHP
php用正则表达式匹配URL的简单方法
Nov 12 PHP
PHP魔术引号所带来的安全问题分析
Jul 15 PHP
php中socket通信机制实例详解
Jan 03 PHP
一张表搞清楚php is_null、empty、isset的区别
Jul 07 PHP
php正则表达式获取内容所有链接
Jul 24 PHP
PHP版微信第三方实现一键登录及获取用户信息的方法
Oct 14 PHP
laravel5.6框架操作数据curd写法(查询构建器)实例分析
Jan 26 PHP
php 输出缓冲 Output Control用法实例详解
Mar 03 PHP
PHP 8新特性简介
Aug 18 PHP
Laravel中GraphQL接口请求频率实战记录
Sep 01 #PHP
PHP实现Snowflake生成分布式唯一ID的方法示例
Aug 30 #PHP
Yii实现微信公众号场景二维码的方法实例
Aug 30 #PHP
Swoole源码中如何查询Websocket的连接问题详解
Aug 30 #PHP
PHP常用header头定义代码示例汇总
Aug 29 #PHP
PHP isset()及empty()用法区别详解
Aug 29 #PHP
PHP实现简单日历类编写
Aug 28 #PHP
You might like
PHP中strlen()和mb_strlen()的区别浅析
2014/06/19 PHP
详解ThinkPHP3.2.3验证码显示、刷新、校验
2016/12/29 PHP
实例讲解PHP中使用命名空间
2019/01/27 PHP
Laravel如何自定义command命令浅析
2019/03/23 PHP
PHP正则表达式函数preg_replace用法实例分析
2020/06/04 PHP
Laravel如何实现适合Api的异常处理响应格式
2020/06/14 PHP
Jquery跨域获得Json时invalid label错误的解决办法
2011/01/11 Javascript
分享一个用Mootools写的鼠标滑过进度条改变进度值的实现代码
2011/12/12 Javascript
jquery实现点击TreeView文本父节点展开/折叠子节点
2013/01/10 Javascript
JS获取图片lowsrc属性的方法
2015/04/01 Javascript
Jquery promise实现一张一张加载图片
2015/11/13 Javascript
AngularJS中使用HTML5手机摄像头拍照
2016/02/22 Javascript
jQuery给表格添加分页效果
2017/03/02 Javascript
layui表格实现代码
2017/05/20 Javascript
JavaScript取得gridview中获取checkbox选中的值
2017/07/24 Javascript
微信小程序实现图片上传、删除和预览功能的方法
2017/12/18 Javascript
webpack多页面开发实践
2017/12/18 Javascript
JS装饰器函数用法总结
2018/04/21 Javascript
Vue scrollBehavior 滚动行为实现后退页面显示在上次浏览的位置
2019/05/27 Javascript
layui写后台表格思路和赋值用法详解
2019/11/14 Javascript
Vue2.0 ES6语法降级ES5的操作
2020/10/30 Javascript
解决vue页面刷新,数据丢失的问题
2020/11/24 Vue.js
Python导入txt数据到mysql的方法
2015/04/08 Python
浅谈python内置变量-reversed(seq)
2017/06/21 Python
python实现周期方波信号频谱图
2018/07/21 Python
python opencv pytesseract 验证码识别的实现
2020/08/28 Python
BannerBuzz加拿大:在线定制横幅印刷、广告和标志
2020/03/10 全球购物
介绍一下Java的安全机制
2012/06/28 面试题
数控专业大学毕业生职业规划范文
2014/02/06 职场文书
安全协议书范本
2014/04/21 职场文书
教师见习期自我鉴定
2014/04/28 职场文书
公开承诺书格式
2014/05/21 职场文书
国际贸易实训报告
2014/11/05 职场文书
2014年物资管理工作总结
2014/12/02 职场文书
Python中的min及返回最小值索引的操作
2021/05/10 Python
java设计模式--原型模式详解
2021/07/21 Java/Android