PHP动态数组路径访问
我可以轻松地写入和读取会话数组中的子数组PHP动态数组路径访问,php,arrays,Php,Arrays,我可以轻松地写入和读取会话数组中的子数组 $_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;
$_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组件,名为。您可以按如下方式使用它:
$persons = array('a' => array('b' => 5.7));
$accessor = PropertyAccess::createPropertyAccessor();
echo $accessor->getValue($persons, '[a][b]'); // 5.7
您可以使用文档中描述的Composer安装它,也可以直接从中获取
自定义解决方案
这是一个完整的解决方案,它的有效性给我留下了深刻的印象。。。但它是有效的!检查下面的代码,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'));
几天前我也遇到过同样的问题,由于我没有找到任何解决方案,我自己做了一个,如果这对你有帮助的话(只是有趣的部分):
谢谢托马斯兹。虽然我现在不想使用新的框架,但我相信我可以浏览Symfony代码,看看他们是如何做到的。请参阅我的更新答案,我提供的解决方案没有第三方代码。但是仔细研究一下这个组件,你不需要使用框架就可以在你的项目中只使用它。请注意,你不需要整个框架,symfony以解耦而闻名,您只能使用PropertyAcces组件,而不需要回答中所述的其余框架代码。这些Symfony2组件是专门设计用于任何地方的,它们不绑定到任何框架。@user1032531我更新的回答解决了您的问题吗?谢谢Clement,现在就看一下您的脚本。您是否有实际设置值的方法。@user1032531设置什么值<代码>$Access->getFromPrefix($MyTestArray)=“我的新值”代码>?如果在这种情况下不可能设置值,那么设置值将很困难-您可以尝试通过获取数组元素的引用来修改它们,但这不是编写或维护的好代码。@user1032531啊,对,我不好,我明白您的意思,是的,我也有一个setFromPrefix方法,但现在无法访问代码,如果你还需要的话,我今晚会修改我的答案。(是的,它比getter更难一点)。无论如何,我认为使用Symfony解决方案听起来更可靠。最后一个
var\u dump()
应该返回array('Toto'=>'Works')
,你不这样认为吗?不管怎样,检查我的答案,我用更简单的方式解决了这两个问题。
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