php中获取不到当前元素,PHP 中数组获取不到元素

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

3a3feff74c8daa2ce917aff41c41b71e.png

可以看到数组存在索引 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);

将会输出:

7294856053a3994eb503a9266cf62bba.png

可以看到存入到数组里面的 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);

将会输出

a181b18a8b3c25bc0c7cabc8d5698c6d.png

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

1

2

$a=(array)$o;

print_r($a);

将会输出

3789cb00284573a24866617df64c455f.png

接下来尝试访问数组 $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;

将会输出

bbfa0f890f3720a189dc2e6c6a9ed036.png

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

1

2

var_dump($a);

var_dump($a2);

将会输出

618453fd4434bcc575f67a55ed9a4bdd.png

从这个输出我们可以看到数组 $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

$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($aas$k=>$v){

var_dump($k);

var_dump($v);

}

--本文来源于网络

原文:http://www.cnblogs.com/kl0428/p/6394831.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值