php 回调传参数组,php函数引用传参数组:function set(array &$array, $path, $value)

php函数引用传参数组:function set(array &$array, $path, $value)

function set(array &$array, $path, $value)

{

print_r($array);

echo('


');

$segments = explode('.', $path);

while(count($segments) > 1)

{

$segment = array_shift($segments);

if(!isset($array[$segment]) || !is_array($array[$segment]))

{

$array[$segment] = [];

}

$array =& $array[$segment];

print_r($array);

echo('


');

}

$array[array_shift($segments)] = $value;

print_r($array);

echo('


');

}

$arr = ['a' => 1, 'b' => 2, 'c' => 3];

set($arr, 'a.b.d', 4);

print_r($arr);

结果:

Array ( [a] => 1 [b] => 2 [c] => 3 )

Array ( )

Array ( )

Array ( [d] => 4 )

Array ( [a] => Array ( [b] => Array ( [d] => 4 ) ) [b] => 2 [c] => 3 )

为什么最终结果不是Array ( [d] => 4 ),而是 Array ( [a] => Array ( [b] => Array ( [d] => 4 ) ) [b] => 2 [c] => 3 ) ?

这个怎么解: $array =& $array[$segment];

首先,如果语句$array =& $array[$segment]中的&符号去掉,结果就如楼主所期待的最后输出Array([d] => 4)。显然问题的关键就在那一句的&上面。

我们知道php在存储变量和变量的值时分别用了两种数据结构zval和zval_value。在zval中包含四个字段:

refcount_gc 表示引用计数

is_ref_gc 表示是否为引用

value 存储变量标识符

type 变量的具体类型

变量的实际值存储在另一个联合体中,具体结构省略。现在我们来模拟一下过程:

首先$arr = ['a' => 1, 'b' => 2,'c' => 3]创建:

arr{'refcount_gc':1, 'is_ref_gc':0,'value':'arr','type':array}(后面将会省略value和type的书写),同时创建array类型的zval_value。

['a']{'refcount_gc':1, 'is_ref_gc':0, ...}

['b']{'refcount_gc':1, 'is_ref_gc':0, ...}

['c']{'refcount_gc':1, 'is_ref_gc':0, ...}

在调用set方法时,传递的是$arr的一个引用:&arr{'refcount_gc':2, 'is_ref_gc':1, ...}

接着进入函数体,while循环内,第一次由于!is_array($arr['a'])成立,为$arr['a']赋值空数组。

['a']{'refcount_gc':1, 'is_ref_gc':0, ...},并创建类型为array的zval_value。

$arr =& $arr['a'];这一句又将原数组的['a']转为引用['a']:{'refcount_gc':2, 'is_ref_gc':1, ...},它和arr都同时是这个空数组的引用①。

接着第二次循环,由于此时arr是一个空数组的引用,!isset($arr['b'])成立,为$arr['b']赋值空数组。

arr['b']{'refcount_gc':2, 'is_ref_gc':1, ...},并创建类型为array的zval_value,同时由于①,原来数组的['a']也是这个空数组的引用, 也就是在原数组['a']基础上有了['a']['b']②。

$arr =& $arr['b'];这一句又将arr['b']转为引用arr['b']:{'refcount_gc':3, 'is_ref_gc':1, ...},由于②,①中的空数组的['b'],原数组的['a']['b']和arr都同时是这个空数组的引用③。

然后退出循环。

$arr['d'] = 4;为②中的空数组创建索引['d'],且由于③,原数组的['a']['b']、①中数组的['b']也是这个数组的引用,他们都指向了这个(['d'] => 4)的数组。

所以最后打印原数组出来的就是Array ( [a] => Array ( [b] => Array ( [d] => 4 ) ) [b] => 2 [c] => 3 )

简化的图示为:

2884243171-5527fd5835aa2_articlex.png

画的比较随意。。大致按数字步骤体现其过程。。。

问题主要出现在

while(count($segments) > 1)

{

$segment = array_shift($segments);

if(!isset($array[$segment]) || !is_array($array[$segment]))

{

$array[$segment] = [];

}

//这里传引用赋值,将$array[$segment]的引用传给了$array

//所以此后的$array已经不再指向传参近来的那个$array(但传参进来的那个$array并未消失)

//最简单的方法是将这个&去掉,在输出一遍,你应该就明白了

$array =& $array[$segment];

print_r($array);

echo('


');

}

运行一下,如果不明白有问题可以留言

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值