PHP多维数组eval与循环实现以及效率
框架里有个获取多维数组配置参数 赋值和取值 的功能,之前是简单的使用 eval 实现的,但感觉使用 eval 是不太好的办法,一直想用其他办法取代
1. eval 的安全问题,2 性能问题,3 服务器\空间兼容性问题 禁用 eval
前段时间测试了下 循环来实现,但没有成功,今天重写功能,终于实现了多维数组自动赋值与取值功能,不需要使用递归
环境:PHP5.4.7,以下展示代码是从我测试代码中提取出来,只展示主要实现,如要自己测试还需要重新整理下
数据,示例已存在的一组数组:
1
2
3
4
5
6
7
8
|
$c
[
'a'
][
'a1'
][
'a2'
][
'a3'
][
'a4'
][
'a5'
] =
'a'
;
$c
[
'a'
][
'a1'
][
'a2'
][
'a3'
][
'a4'
][
'a6'
] =
'a'
;
$c
[
'b'
][
'b1'
][
'b2'
][
'b3'
][
'b4'
][
'b5'
] =
'b'
;
$c
[
'b'
][
'b1'
][
'b2'
][
'b3'
][
'b4'
][
'b6'
] =
'b'
;
$c
[
'c'
][
'c1'
][
'c2'
][
'c3'
][
'c4'
][
'c5'
] =
'c'
;
$c
[
'c'
][
'c1'
][
'c2'
][
'c3'
][
'c4'
][
'c6'
] =
'c'
;
$c
[
'd'
][
'd1'
][
'd2'
][
'd3'
][
'd4'
][
'd5'
] =
'd'
;
$c
[
'e'
][
'e1'
][
'e2'
][
'e3'
][
'e4'
][
'e6'
] =
'e'
;
|
指定取值\赋值节点:
1
|
$key
=
'a.a1.a2.a3.a4.a5'
;
|
一、多维数组赋值:
1. 简单方法使用 eval
1
|
eval
(
'$c[\''
.
str_replace
(
'.'
,
'\'][\''
,
$key
) .
'\'] = $value;'
);
|
2. 使用循环赋值
1
2
3
4
5
6
7
8
9
10
11
12
|
$nodes
=
explode
(
'.'
,
$key
);
$config
= &
$c
;
foreach
(
$nodes
as
$node
) {
if
(isset(
$config
[
$node
])) {
$config
= &
$config
[
$node
];
}
else
{
$config
[
$node
] =
array
();
$config
= &
$config
[
$node
];
}
}
$config
=
$value
;
|
二、多维数组取值:
1. 简单方法使用 eval,(实际部署还应该加入 isset 判断后取值才行)
1
|
eval
(
'$value = $c[\''
.
str_replace
(
'.'
,
'\'][\''
,
$key
) .
'\'];'
);
|
2. 使用循环取值
1
2
3
4
5
6
7
8
9
10
11
|
$value
=
$config
;
$nodes
=
explode
(
'.'
,
$key
);
foreach
(
$nodes
as
$node
) {
if
(isset(
$value
[
$node
])) {
$value
=
$value
[
$node
];
}
else
{
$value
= null;
break
;
}
}
|
针对 PHP5.4 的取值应该还有一种简便的方法:
1
2
3
4
5
6
7
|
function
g() {
global
$c
;
return
$c
;
}
echo
'<pre>'
;
$a
= g()[
'a'
][
'a1'
][
'a2'
][
'a3'
][
'a4'
];
print_r(
$a
);
|
也许感觉起来还是有些复杂吧,特别是当某一维度元素不存在时无法判断
以上代码的应用方式可简单封装为:
1
2
3
4
5
|
set(
$nodes
,
$value
);
set(
'a.a1.a2.a3.a4.a5'
,
'test'
);
get(
$nodes
);
get(
'a.a1.a2.a3.a4.a5'
);
|
这样再深的维度也不怕
---------------------------------------------------------------------------------------
大概实现过程就是这样,已经过多种方式测试没有问题,下面说下测试的性能:
过程没什么可多说的,直说结果了:
---------------------------------------------------------------------------------------
1000000 一百万次循环的比较:
赋值 速度:
eval 用时:36秒
循环用时 :17秒
相差至少两倍;
取值速度:
eval用时:33秒
循环用时:7秒
相差近5倍左右
维度加深测试:
循环 和 eval 差别不大,
维度6级增加到13级时平均每加深一级,赋值耗时增加约 0.7秒,取值增加 0.3秒
----------------------------------------------------------------------------------------
其他提示:
-
首先总体性能跟数组体积有关这是肯定的;
-
数组维数深度对性能的影响不是特别大,我上面测试使用的是13维深度,普通应用基本上都在4维以下吧,所以深度问题带来的性能问题几乎可以忽略。
-
另外根据我之前看到的一些文章总结推荐使用多维数组而不是分散的数组存储数组,有效利用内存,总体性能也许更好;