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