function set(array &$array, $path, $value)
{
    print_r($array);
    echo('<br>
<hr>
');
    $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('<br><hr>');
    }
    $array[array_shift($segments)] = $value;
    print_r($array);
    echo('<br><hr>');
}
$arr = ['a' => 1, 'b' => 2, 'c' => 3];
set($arr, 'a.b.d', 4);
print_r($arr);
结果:
为什么最终结果不是Array ( [d] => 4 ),而是 Array ( [a] => Array ( [b] => Array ( [d] => 4 ) ) [b] => 2 [c] => 3 ) ?
这个怎么解: $array =& $array[$segment];
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
首先,如果语句
$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 )简化的图示为:

画的比较随意。。大致按数字步骤体现其过程。。。
问题主要出现在
运行一下,如果不明白有问题可以留言