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
. zval
contains four fields in:
refcount_gc
Represents a reference count
is_ref_gc
Indicates whether it is a reference
value
Store variable identifiers
type
Specific 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 callset
method, you pass the$arr
A reference to:&arr{'refcount_gc':2, 'is_ref_gc':1, ...}
And then into the function body,while
Within 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 andarr
Both 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