【注意】最后更新于 March 29, 2019,文中内容可能已过时,请谨慎使用。
关于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
29
30
31
32
33
34
|
//处理前长这样
$arr = [
'home/work/whf/cors/test1.conf',
'home/work/whf/cor/test2.conf',
'home/caros/conf/param/test3.conf',
'home/test6.conf',
'home/test7.conf',
'home/work/test8.conf'
];
//处理后长这样
$arr = [
'home' => [
'work' => [
'whf' => [
'cors' => [
'test1.conf'
],
'cor' => [
'test1.conf' => []
]
],
'test8' => []
],
'caros' => [
'conf' => [
'param' => [
'test3.conf' => []
]
]
]
],
'test6.conf' => [],
'test7.conf' => [],
];
|
好家伙,这不是循环下就解决了吗?二话不说,便开始撸码。
但是写着写着我发现不对劲,这道题看似简单,但真的撸起代码来会发现简单的循环搞定不了它。此时还认为很简单的同学可以先不要往下看,动手试试你就会发现自己低估这道题。
要想解决这道题,php的引用原理必须要了解。
PHP引用原理
php的引用可以分为三类:1、变量的引用 2、函数的引用(传递) 3、函数的引用(返回)4、对象的引用
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
29
30
31
32
33
34
35
36
37
38
39
40
41
|
//-----------------------------------------1、变量的引用
$a = "ABC";
$b = &$a;
echo $a; //这里输出:ABC
echo $b; //这里输出:ABC
$b = "EFG";
echo $a; //这里$a的值变为EFG 所以输出EFG
echo $b; //这里输出EFG
//-----------------------------------------2、函数的引用(传递)
function test(&$a){
$a = $a + 100;
}
$b = 1;
test($b); //这里$b传递给函数的其实是$b的变量内容所处的内存地址,通过在函数里改变$a的值 就可以改变$b的值了
echo $b; //输出101
//-----------------------------------------3、函数的引用(返回)
function &test(){
static $b = 0; //申明一个静态变量
$b = $b + 1;
echo $b;
return $b;
}
$a = test(); //这条语句会输出 $b的值为1
$a = 5;
$a = test(); //这条语句会输出 $b的值为2
$a = &test(); //这条语句会输出 $b的值为3
$a = 5;
$a = test(); //这条语句会输出 $b的值为6 由此可见,test()的返回值$b被赋值在了$a,等同于$a = &$b,所以修改$a的同时也会修改$b
//-----------------------------------------4、对象的引用
class a{
var $abc = "ABC";
}
$b = new a;
$c = $b;
echo $b->abc; //这里输出ABC
echo $c->abc; //这里输出ABC
$b->abc = "DEF";
echo $c->abc; //这里输出DEF,上述代码等同于$b = new a;$c = &$b;
//PHP5以上默认就是通过引用来调用对象,但有时你可能想建立一个对象的副本,并希望原来的对象的改变不影响到副本,可以使用__clone。
|
解题
有了php引用的知识,解这道题就不难了,只需要用到变量的引用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
$arr = [
'home/work/whf/cors/test1.conf',
'home/work/whf/cor/test2.conf',
'home/caros/conf/param/test3.conf',
'home/test6.conf',
'home/test7.conf',
'home/work/test8.conf'
];
$ret = [];
foreach ($arr as $k => $v) {
$temp = explode('/', $v);
$temp2 = &$ret;
foreach ($temp as $vv) {
if (!$temp2[$vv]){
$temp2[$vv] = [];
}
$temp2 = &$temp2[$vv];
}
}
return $ret;
|
通过这种方法,$temp2不断的成为替身,打进$ret的内部。
原谅我有点词穷,不过Talk is cheap Show me the code,大家看代码就行了。