关于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,大家看代码就行了。