Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP动态访问变量值_Php_Variables - Fatal编程技术网

PHP动态访问变量值

PHP动态访问变量值,php,variables,Php,Variables,我想动态访问变量的值,假设我有这个数组: $aData = array( 'test' => 123 ); 打印测试键值的标准方法是: print $aData['test']; 但是,如果我必须使用变量的字符串表示(出于动态目的) 如何实现打印名为test的aData键?下面提供的两个示例都不起作用 print $$sItem; print eval($sItem); 解决方案是什么?在您的情况下,唯一的解决方案是使用 但是在做这件事的时候请非常小心!Eval将计算(并执行)作

我想动态访问变量的值,假设我有这个数组:

$aData = array(
  'test' => 123
);
打印
测试
键值的标准方法是:

print $aData['test'];
但是,如果我必须使用变量的字符串表示(出于动态目的)

如何实现打印名为
test
aData
键?下面提供的两个示例都不起作用

print $$sItem;
print eval($sItem);

解决方案是什么?

在您的情况下,唯一的解决方案是使用

但是在做这件事的时候请非常小心!Eval将计算(并执行)作为PHP传递给它的任何参数。因此,如果您将用户提供的内容提供给它,那么任何人都可以在您的服务器上执行任何PHP代码,这无疑是一个大峡谷大小的安全漏洞


编辑:您必须在
$sItem
变量中添加一个“print”或“echo”。它必须在
$sItem
$sItem='echo$aData[\'test\'];
)中,或者您必须这样编写
Eval()
:Eval('echo'.$sData)

您可以像普通数组一样使用它:

$key = "test";

print $aData[$key];
同样地,
$aData
本身也可以是较大数组存储中的一个条目


作为替代方案,可以使用正则表达式提取潜在的数组键,并使用引用遍历匿名数组(在您的问题中应该提到,if)。请参阅和类似主题


就我个人而言,我使用这样的构造来利用动态变量路径,比如
varname[keyname]
(类似于PHP解释GET参数的方式)。这只是绵羊服装中的评估(尽管不同意评估恐慌的说法):


您的评估示例缺少返回值:

print eval("return $sItem;");
应该这样做:

$aData['test'] = 'foo';

$sItem = '$aData[\'test\']';

print eval("return $sItem;"); # foo
但不建议正常使用eval。你可以带着它去地狱厨房,因为eval是邪恶的

相反,只需解析字符串并返回值:

$aData['test'] = 'foo';

$sItem = '$aData[\'test\']';

$r = sscanf($sItem, '$%[a-zA-Z][\'%[a-zA-Z]\']', $vName, $vKey);
if ($r === 2)
{
    $result = ${$vName}[$vKey];
}
else
{
    $result = NULL;
}

print $result; # foo
这也可以通过其他形式的正则表达式来实现

由于您的语法非常接近PHP,实际上是PHP的一个子集,因此如果您想在使用eval之前验证输入,可以使用一些替代方法。方法是对照PHP标记进行检查,并且只允许一个子集。这不会验证字符串(例如语法和是否实际设置了变量),但会使其更加严格:

function validate_tokens($str, array $valid)
{
    $vchk = array_flip($valid);
    $tokens = token_get_all(sprintf('<?php %s', $str));
    array_shift($tokens);
    foreach($tokens as $token)
        if (!isset($vchk[$token])) return false;
    return true;
}
然后,您就可以使用它,它也可以与更复杂的键一起使用:

$aData['test'] = 'foo';
$aData['te\\\'[]st']['more'] = 'bar';

$sItem = '$aData[\'test\']';
$vValue = NULL;
if (validate_tokens($sItem, array(309, 315, '[', ']')))
{
    $vValue = eval("return $sItem;");
}
我用这个来回答这个问题


如其他aldready解释的那样,请谨慎使用。

如果您已经(或能够)将数组名称和键输入到单独的变量中,则无需进行评估:

$aData = array(
  'test' => 123
);

$arrayname = 'aData';
$keyname = 'test';

print ${$arrayname}[$keyname]; // 123

你可以用这个方法

function getRecursive($path, array $data) {
        // transform "foo['bar']" and 'foo["bar"]' to "foo[bar]"
        $path = preg_replace('@\[(?:"|\')(.+)(?:"|\')\]@Uis', '[\1]', $path);

        // get root
        $i = strpos($path, '[');
        $rootKey = substr($path, 0, $i);
        if (!isset($data[$rootKey])) {
            return null;
        }
        $value = $data[$rootKey];

        $length = strlen($path);
        $currentKey = null;
        for (; $i < $length; ++$i) {
            $char = $path[$i];

            switch ($char) {
                case '[':
                    if ($currentKey !== null) {
                        throw new InvalidArgumentException(sprintf('Malformed path, unexpected "[" at position %u', $i));
                    }
                    $currentKey = '';
                    break;
                case ']':
                    if ($currentKey === null) {
                        throw new InvalidArgumentException(sprintf('Malformed path, unexpected "]" at position %u', $i));
                    }

                    if (!isset($value[$currentKey])) {
                        return null;
                    }

                    $value = $value[$currentKey];
                    if (!is_array($value)) {
                        return $value;
                    }

                    $currentKey = null;
                    break;
                default:
                    if ($currentKey === null) {
                        throw new InvalidArgumentException(sprintf('Malformed path, unexpected "%s" at position %u', $char, $i));
                    }
                    $currentKey .= $char;
                    break;
            }
        }

        if ($currentKey !== null) {
            throw new InvalidArgumentException('Malformed path, must be and with "]"');
        }

        return $value;
    }
函数getRecursive($path,array$data){ //将“foo['bar']”和“foo['bar']”转换为“foo[bar]” $path=preg\u replace('@\[(?:“\\”)(.+)(?:“\\”)\]@Uis','[\1]',$path); //扎根 $i=strpos($path,['); $rootKey=substr($path,0,$i); 如果(!isset($data[$rootKey])){ 返回null; } $value=$data[$rootKey]; $length=strlen($path); $currentKey=null; 对于(;$i<$length;++$i){ $char=$path[$i]; 交换机($char){ 案例“[”: 如果($currentKey!==null){ 抛出新的InvalidArgumentException(sprintf('格式错误的路径,位置%u'处意外出现“[”,$i)); } $currentKey=''; 打破 案例']': 如果($currentKey==null){ 抛出新的InvalidArgumentException(sprintf('格式错误的路径,位置%u'处意外出现“]”,$i)); } 如果(!isset($value[$currentKey])){ 返回null; } $value=$value[$currentKey]; 如果(!是_数组($value)){ 返回$value; } $currentKey=null; 打破 违约: 如果($currentKey==null){ 抛出新的InvalidArgumentException(sprintf('格式错误的路径,位置%u'处意外的“%s”,$char,$i)); } $currentKey.=$char; 打破 } } 如果($currentKey!==null){ 抛出新的InvalidArgumentException('格式错误的路径,必须是且带有“]”); } 返回$value; }
除了您可能指的是打印$aData[$key],而不是$aData[$test之外,这是目前为止最好的解决方案+1如果您忽略了被问到的问题,那么这是最好的解决方案,是的!:)+1.我认为这是唯一合理、有效的解决办法。无论其他人建议如何使用
eval
,他们都不会返回键
test
。也许某些正则表达式字符串解析可以实现提取密钥,但eval永远无法根据OP获取字符串的方式来实现这一点。@JanHančič被询问的是密钥,而不是结果。两个
eval
示例都无法检索密钥。hakre的字符串解析解决方案确实有效,但这是一个迂回的过程。为什么你要把密钥分配给一个字符串变量的子字符串,然后必须遍历整个字符串来获取密钥,而你可以随时准备好密钥。@JanHančič也许,你可能是对的。如果问题是访问该值,那么您是对的。但是,我们必须等待OP的回复,看看我是否理解。:)根据他的问题,这是。@all:谢谢你们,从我的计划来看(在大图中),使用eval函数对我来说是最好的解决方案。。。我只是忘了使用return,这是个好方法。但是,一个
preg\u match\u all
就足以在
$aData['test'] = 'foo';
$aData['te\\\'[]st']['more'] = 'bar';

$sItem = '$aData[\'test\']';
$vValue = NULL;
if (validate_tokens($sItem, array(309, 315, '[', ']')))
{
    $vValue = eval("return $sItem;");
}
$sItem = '$aData[\'test\']';
eval('$someVar = '.$sItem.';');
echo $someVar;
$aData = array(
  'test' => 123
);

$arrayname = 'aData';
$keyname = 'test';

print ${$arrayname}[$keyname]; // 123
function getRecursive($path, array $data) {
        // transform "foo['bar']" and 'foo["bar"]' to "foo[bar]"
        $path = preg_replace('@\[(?:"|\')(.+)(?:"|\')\]@Uis', '[\1]', $path);

        // get root
        $i = strpos($path, '[');
        $rootKey = substr($path, 0, $i);
        if (!isset($data[$rootKey])) {
            return null;
        }
        $value = $data[$rootKey];

        $length = strlen($path);
        $currentKey = null;
        for (; $i < $length; ++$i) {
            $char = $path[$i];

            switch ($char) {
                case '[':
                    if ($currentKey !== null) {
                        throw new InvalidArgumentException(sprintf('Malformed path, unexpected "[" at position %u', $i));
                    }
                    $currentKey = '';
                    break;
                case ']':
                    if ($currentKey === null) {
                        throw new InvalidArgumentException(sprintf('Malformed path, unexpected "]" at position %u', $i));
                    }

                    if (!isset($value[$currentKey])) {
                        return null;
                    }

                    $value = $value[$currentKey];
                    if (!is_array($value)) {
                        return $value;
                    }

                    $currentKey = null;
                    break;
                default:
                    if ($currentKey === null) {
                        throw new InvalidArgumentException(sprintf('Malformed path, unexpected "%s" at position %u', $char, $i));
                    }
                    $currentKey .= $char;
                    break;
            }
        }

        if ($currentKey !== null) {
            throw new InvalidArgumentException('Malformed path, must be and with "]"');
        }

        return $value;
    }