PHP 中数组获取不到元素
早上看到 SO 上一个有关 PHP 的问题,提问者描述有一个数组,使用 print_r 可以看到索引 key 和相对应的 value 都是存在的,但是访问该元素,不管是使用 array[key] 还是 array[‘key’] 这两种访问形式,都提示 Undefined offset 而取不到数据。举例描述提问者的问题,假设一个数组 $a,print_r($a) 的输出为

可以看到数组存在索引 1 值为 foo,当使用 $a[1] 或者 $a[‘1’] 访问索引为 1 的元素,都提示 Undefined offset,这就有点让人费解了,下文将讲解这个问题产生的原因,以及如何得到像这样奇怪的一个数组。
首先说明一点,PHP 中数组的 key 可以为整形和字符串,但是包含有合法整型值的字符串会被转换为整型。例如键名 “1” 实际会被储存为 1。来看一个例子,考虑如下代码:
|
1
2
3
4
5
6
7
|
$a = array(
1 => 'foo',
'1' => 'bar',
'name' => 'upliu',
);
print_r($a);
var_dump($a);
|
将会输出:

可以看到存入到数组里面的 1 为数值索引(注意索引 name 加了引号,说明索引 name 为字符串索引(这不废话嘛,’name’ 肯定是字符串啊)),并且值为 bar 覆盖了先出现的 foo,$a[1] 和 $a[‘1’] 都能正确读取到 bar,且没有任何错误警告提示,说明这个两者都是可用的(笔者在此猜测 $a[‘1’] 实际上完全等效于 $a[1],PHP 数组读取元素的时候会将数值字符串索引转换为数值索引)。
我们先还原一下提问者的问题,看如何生产出那样一个数组。考虑如下代码:
|
1
2
3
|
$json = '{"1":"foo"}';
$o = json_decode($json);
var_dump($o);
|
将会输出

这个结果很显而易见,$o 为一个对象,有一个属性为 1,因为该属性并不是合法的 PHP 标识符,因此不能使用箭头的方式访问,我们使用强制类型转换将该对象转换为一个数组:
|
1
2
|
$a = (array)$o;
print_r($a);
|
将会输出

接下来尝试访问数组 $a 的索引为 1 的元素:
|
1
2
|
echo $a[1], PHP_EOL;
echo $a['1'], PHP_EOL;
|
上面两条语句均会报错 Undefined offset,这时数组 $a 就是 SO 上那位提问者遇到问题时碰到的数组了,BUG 重现是一件很爽的事啊。
我们来直接将上面代码中的 json 串解析为数组:
|
1
2
3
4
|
$a2 = json_decode($json, true);
print_r($a2);
echo $a2[1], PHP_EOL;
echo $a2['1'], PHP_EOL;
|
将会输出

一切正常,这个时候问题来了,明明数组 $a 和数组 $a2 使用 print_r 输出一模一样,为什么一个元素可以访问,另一个却不能访问。我们用更强大的 var_dump 看看:
|
1
2
|
var_dump($a);
var_dump($a2);
|
将会输出

从这个输出我们可以看到数组 $a 和 $a2 的不同,通过将对象强制类型转换得到的数组 $a 拥有一个字符串 ‘1’ 的索引(可以使用 var_dump(array_keys($a))来证实这一点),而我们使用 $a[1] 和 $a[‘1’] 都是访问数组 $a 中索引为 1 的元素,而 $a 并不存在该元素,因此出现错误 Undefined offset。
小结:PHP 默认不会存储整型字符串的索引,会将其转换为数值,在将对象转换为数组的过程中可能引入整型字符串的索引,如果给出索引为整数或整形字符串,访问数组元素都会去获取数组的对应数值索引。
本文实例完整代码如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
<?php
$json = '{"1":"foo"}';
$o = json_decode($json);
$a = (array)$o;
print_r($a);
echo $a[1], PHP_EOL;
echo $a['1'], PHP_EOL;
$a2 = json_decode($json, true);
print_r($a2);
echo $a2[1], PHP_EOL;
echo $a2['1'], PHP_EOL;
var_dump($a);
var_dump($a2);
var_dump(array_keys($a));
var_dump(array_keys($a2));
foreach ($a2 as $k => $v) {
var_dump($k);
var_dump($v);
}
foreach ($a as $k => $v) {
var_dump($k);
var_dump($v);
}
|
--本文来源于网络
PHP 中数组获取不到元素的更多相关文章
- javascript中DOM获取和设置元素的内容、样式及效果
getElementById() 根据id获取dom元素 没有找到则返会Null <!DOCTYPE html> <html lang="en"> < ...
- Java中数组获取最大值
最大值获取:从数组的所有元素中找出最大值. 实现思路: 定义变量,保存数组0索引上的元素 遍历数组,获取出数组中的每个元素 将遍历到的元素和保存数组0索引上值的变量进行比较 如果数组元素的值大于了变量 ...
- jsp中Java代码中怎么获取jsp页面元素
举例,页面元素<td><input value="${sl }" type="text" id="sl" name=& ...
- 在Javascript中数组对象(json)里元素相同的操作
1.数组对象元素相同,分组显示 let arry = [ { expensedate: '2018/09/29', amount: 1, type: '交通费' }, { expensedate: ...
- JQuery 数组获取和删除元素
<script> var target = []; target [0] = "aaa000"; target [1] = "bbb111"; ta ...
- vue中mounted中无法获取到dom元素
一.解决方案: 加上异步setTimeout,延迟获取dom的代码的执行 mounted() { // debugger this.$nextTick(()=> { setTimeout(()= ...
- AngularJs在ng-click函数中如何获取代表当前元素的DOM对象
<!DOCTYPE html> <html> <head> <title></title> <script src="lib ...
- js在数组arr中随机获取count数量的元素
// 在数组arr中随机获取count数量的元素; const getRandomArrayElements = (arr, num) => { // 新建一个数组,将传入的数组复制过来,用于运 ...
- LINQ 获取当前数组中出现次数最多的元素
LINQ 获取当前数组中出现次数最多的元素 1 List<string> a = new List<string>(); a.Add( ...
随机推荐
- Pomelo.AspNetCore.TimedJob 允许依赖注入
public static IWebHost BuildWebHost(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStar ...
- 通过java反射机制获取该类的所有属性类型、值
转自:http://blog.csdn.net/sd4000784/article/details/7448221 方法使用了这俩个包下的 field 和method import Java.lang ...
- 可能是全网首个支持阿里云Elasticsearch Xapck鉴权的Skywalking
可能是全网首个支持阿里云Elasticsearch Xapck鉴权的Skywalking 对Skywalking有兴趣的同学参见:年轻人的第一个APM-Skywalking 之前在搭建Skywalki ...
- Python运维三十六式:用Python写一个简单的监控系统
市面上有很多开源的监控系统:Cacti.Nagios.Zabbix.感觉都不符合我的需求,为什么不自己做一个呢? 用Python两个小时徒手撸了一个简易的监控系统,给大家分享一下,希望能对大家有所启发 ...
- Sublime Text 3安装完美的Vim支持,ActualVim/NeoVim
很多IDE和编辑器都有Vim插件用于支持Vim模式,但大多数都有些问题,拿我一直用的Idea来说,它的vim在ctrl+v后,选择多行的行前插入,如果这几行中有空行,它不会把空格算在内,所以最终是会少 ...
- python接口自动化1-发送get请求 前言
前言 requests模块,也就是老污龟,为啥叫它老污龟呢,因为这个官网上的logo就是这只污龟,接下来就是学习它了. 一.环境安装 1.用pip安装requests模块 >>pip in ...
- dubbo 微服务框架
dubbo 注解配置: @Service //Service注解暴露服务 @Configuration // javaconfig形式配置公共模块 @DubboComponentScan // 指定d ...
- 高可用Kubernetes集群-4. kubectl客户端工具
六.部署kubectl客户端工具 1. 下载 [root@kubenode1 ~]# cd /usr/local/src/ [root@kubenode1 src]# wget https://sto ...
- HP VC模块Server Profile配置快速参考(With SUS)
以管理员身份登录VCM 准备进行Server Profiles的配置 在左侧导航栏中找到并点击"Server Profiles",在右侧主窗口的左下角点击"Add&quo ...
- 关于Amazon.com Seller 网络以及IP地址更换 官方回答
Greetings from Amazon Seller Support, I understand your concern that there will be a change of IP ad ...