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 相关文章推荐
实现dedecms全站URL静态化改造的代码
Mar 29 PHP
php实现用户在线时间统计详解
Oct 08 PHP
PHP中文件读、写、删的操作(PHP中对文件和目录操作)
Mar 06 PHP
PHP 面向对象详解
Sep 13 PHP
解决phpmyadmin中缺少mysqli扩展问题的方法
May 06 PHP
PHP模板引擎Smarty的缓存使用总结
Apr 24 PHP
php下foreach提示Warning:Invalid argument supplied for foreach()的解决方法
Nov 11 PHP
typecho插件编写教程(五):核心代码
May 28 PHP
Zend Framework前端控制器用法示例
Dec 11 PHP
ThinkPHP3.2.3框架实现的空模块、空控制器、空操作,跳转到错误404页面图文详解
Apr 03 PHP
Laravel5.1框架注册中间件的三种场景详解
Jul 09 PHP
七种PHP开发环境搭建工具
Jun 28 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者的疑难问答(2)
2006/10/09 PHP
同台服务器使用缓存APC效率高于Memcached的演示代码
2010/02/16 PHP
php垃圾代码优化操作代码
2010/08/05 PHP
php 字符串替换的方法
2012/01/10 PHP
PHP CURL获取cookies模拟登录的方法
2013/11/04 PHP
WordPress中用于获取文章作者与分类信息的方法整理
2015/12/17 PHP
PHP利用二叉堆实现TopK-算法的方法详解
2017/04/24 PHP
基于Jquery+Ajax+Json的高效分页实现代码
2011/10/29 Javascript
Jquery实现鼠标移上弹出提示框、移出消失思路及代码
2013/05/19 Javascript
JS预览图像将本地图片显示到浏览器上
2013/08/25 Javascript
jquery复选框全选/取消示例
2013/12/30 Javascript
用JavaScript实现一个代码简洁、逻辑不复杂的多级树
2014/05/23 Javascript
JS实现表格数据各种搜索功能的方法
2015/03/03 Javascript
jQuery操作动态生成的内容的方法
2016/05/28 Javascript
第十篇BootStrap轮播插件使用详解
2016/06/21 Javascript
纯JS焦点图特效实例(可一个页面多用)
2016/12/07 Javascript
JS实现身份证输入框的输入效果
2017/08/21 Javascript
angular5 httpclient的示例实战
2018/03/12 Javascript
详解Vue中watch的高级用法
2018/05/02 Javascript
微信小程序6位或多位验证码密码输入框功能的实现代码
2018/05/29 Javascript
详解微信小程序用定时器实现倒计时效果
2019/04/30 Javascript
es6 for循环中let和var区别详解
2020/01/12 Javascript
Python实现windows下模拟按键和鼠标点击的方法
2015/03/13 Python
Sanic框架流式传输操作示例
2018/07/18 Python
python xpath获取页面注释的方法
2019/01/14 Python
解决python给列表里添加字典时被最后一个覆盖的问题
2019/01/21 Python
如何安装并使用conda指令管理python环境
2019/07/10 Python
使用Python和Scribus创建一个RGB立方体的方法
2019/07/17 Python
在VS2017中用C#调用python脚本的实现
2019/07/31 Python
Python 防止死锁的方法
2020/07/29 Python
PHP如何防止SQL注入
2014/05/03 面试题
介绍一下Java中的static关键字
2012/05/12 面试题
大学社团活动策划书
2014/01/26 职场文书
《草虫的村落》教学反思
2014/02/16 职场文书
车队安全员岗位职责
2015/02/15 职场文书
关于销售人员的年终工作总结要点
2019/08/15 职场文书