我可以很容易地写入和读取会话数组中的子数组。
$_SESSION['a']['b']['c']['value']=123;
$val=$_SESSION['a']['b']['c']['value'];
不是硬编码写入值的"位置",我希望它可以通过字符串或其他方式定义。下面的代码显然行不通,但希望能更好地解释意图。
$prefix="['a']['b']['c']"; //defined in config page, etc
$_SESSION.$prefix.['value']=123;
$val=$_SESSION.$prefix.['value'];
如何做到这一点?
PropertyAccess
有一个很好的Symfony组件可以完成这样的任务,名为PropertyAccess。你可以这样使用它:$persons = array('a' => array('b' => 5.7));
$accessor = PropertyAccess::createPropertyAccessor();
echo $accessor->getValue($persons, '[a][b]'); // 5.7
你可以按照文档中的描述使用Composer安装它,或者直接从GitHub获取。
自定义解决方案
这是一个完整的解决方案,我真的印象深刻,它的工作…但它确实有效!检查下面的代码,assert()
演示用法:
<?php
function arrayPropertyPathGet(array $arr, $path) {
$parts = explode('.', $path);
$ret = $arr;
foreach($parts as $part) {
$ret = $ret[$part];
}
return $ret;
}
function arrayPropertyPathSet(array &$arr, $path, $value) {
$parts = explode('.', $path);
$tmp = &$arr;
foreach($parts as $part) {
if(!isset($tmp[$part])) { return false; }
$tmp = &$tmp[$part];
}
$tmp = $value;
return true;
}
$test = array('a' => array('b' => 'value'));
assert('value' === arrayPropertyPathGet($test, 'a.b'));
assert(true === arrayPropertyPathSet($test, 'a.b', 'other'));
assert('other' === arrayPropertyPathGet($test, 'a.b'));
边注
作为一个理论边注(不要将其用于学习目的之外的任何事情),您可以尝试使用eval()
,例如:
eval("$value = $persons['a']['b']");
我以前也遇到过同样的问题,因为我没有找到任何解决方案,所以我自己做了一个,如果这对你有帮助的话(只是有趣的部分):
class ArrayAccessor {
private $prefix;
function setPrefix() {
$this->prefix = array();
for ($i = 0; $i < func_num_args(); ++$i) {
$this->prefix[] = func_get_arg($i);
}
}
function getFromPrefix(array $array) {
$tmp_array = $array;
foreach ($this->prefix as $pre) {
if (isset ($tmp_array[$pre])) {
$tmp_array = $tmp_array[$pre];
} else {
return null;
}
}
return $tmp_array;
}
}
$Access = new ArrayAccessor();
$Access->setPrefix('Hi', 'Toto');
$MyTestArray['Hi']['Toto'] = 'Works';
var_dump ($Access->getFromPrefix($MyTestArray));
$Access->setPrefix('Hi');
var_dump ($Access->getFromPrefix($MyTestArray));
$Access->setPrefix('No');
var_dump ($Access->getFromPrefix($MyTestArray));
结果:string(5) "Works"
array(1) {
["Toto"]=>
string(5) "Works"
}
NULL