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);
Results:
Array ([A] = 1 [b] = 2 [c] = 3)
Array ()
Array ()
Array ([d] = 4)
Array ([a] = = Array ([b] = = Array ([d] + 4)) [B] = 2 [c] = 3)
Why the final result is not an array ([d] = 4), but an array ([a] = = Array ([b] = = Array ([d] = 4)) [B] = 2 [c] = 3)?
How to solve this: $array =& $array [$segment];
Reply content:
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);
Results:
Array ([A] = 1 [b] = 2 [c] = 3)
Array ()
Array ()
Array ([d] = 4)
Array ([a] = = Array ([b] = = Array ([d] + 4)) [B] = 2 [c] = 3)
Why the final result is not an array ([d] = 4), but an array ([a] = = Array ([b] = = Array ([d] = 4)) [B] = 2 [c] = 3)?
How to solve this: $array =& $array [$segment];
First, if $array =& $array[$segment] the symbol in the statement is & removed, the result is like the final output expected by the landlord Array([d] => 4) . Obviously the crux of the problem is on top of that sentence & .
We know that php two data structures are used when storing the values of variables and variables zval zval_value . zvalcontains four fields in:
refcount_gcRepresents a reference count
is_ref_gcIndicates whether it is a reference
valueStore variable identifiers
typeSpecific types of variables
The actual value of the variable is stored in another union, and the concrete structure is omitted. Now let's simulate the process:
First of all$arr = ['a' => 1, 'b' => 2,'c' => 3]Create:
arr{'refcount_gc':1, 'is_ref_gc':0,'value':'arr','type':array}(The writing of value and type is omitted later, and the zval_value of the array type is created.)
['a']{'refcount_gc':1, 'is_ref_gc':0, ...}
['b']{'refcount_gc':1, 'is_ref_gc':0, ...}
['c']{'refcount_gc':1, 'is_ref_gc':0, ...}
In the callsetmethod, you pass the$arrA reference to:&arr{'refcount_gc':2, 'is_ref_gc':1, ...}
And then into the function body,whileWithin the loop, for the first time due to!is_array($arr['a'])Established, for$arr['a']An empty array is assigned.
['a']{'refcount_gc':1, 'is_ref_gc':0, ...}, and create a zval_value of type array.
$arr =& $arr['a'];This sentence again will be the original array of['a']Convert to reference['a']:{'refcount_gc':2, 'is_ref_gc':1, ...}, it andarrBoth are reference ① for this empty array.
Then the second loop, because Arr is a reference to an empty array at this point,!isset($arr['b'])Established, for$arr['b']An empty array is assigned.
arr['b']{'refcount_gc':2, 'is_ref_gc':1, ...}and creates a zval_value of type array, and since ①, the original array's['a']is also a reference to this empty array, that is, in the original array['a']On the basis of a['a']['b']Ii.
$arr =& $arr['b'];This sentence will againarr['b']Convert to referencearr['b']:{'refcount_gc':3, 'is_ref_gc':1, ...}, because the empty array in the ②,①['b'], the original array of['a']['b']And arr are both reference ③ for this empty array.
Then exit the loop.
$arr['d'] = 4;To create an index for an empty array in ②['d'], and because of ③, the original array['a']['b'], the array in the ①['b']It's also a reference to this array, and they all point to this(['d'] => 4)The array.
So the final print of the original array isArray ( [a] => Array ( [b] => Array ( [d] => 4 ) ) [b] => 2 [c] => 3 )
The simplified illustrations are:
The painting is more casual. Roughly follow the digital steps to embody its process ...
The problem arises mainly in
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('
'); }
Run, if you do not understand the problem can leave a message