1

我有一组用户输入($atts)作为键=>值对。一些值可以写成数组表达式,例如:

'setting' => 'array(50,25)'

在这些情况下,我想将该字符串中包含的数组表达式转换为实际数组。所以输出会是这样的:

$atts = array(
'setting' => array(50,25),
'another' => 'not written as an array expression'
)

从逻辑上讲,代码将是:

对于数组 $atts 中的每个 key=>value 对...如果该值是格式化为数组表达式的字符串...将该值分解为数组。

有人知道我会如何用 PHP 写这个吗?

4

4 回答 4

3
function stringToArray($string) {
        $string = "return " . $string . ";";
        if (function_exists("token_get_all")) {//tokenizer extension may be disabled
            $php = "<?php\n" . $string . "\n?>";
            $tokens = token_get_all($php);
                        foreach ($tokens as $token) {
                $type = $token[0];
                if (is_long($type)) {
                    if (in_array($type, array(
                            T_OPEN_TAG, 
                            T_RETURN, 
                            T_WHITESPACE, 
                            T_ARRAY, 
                            T_LNUMBER, 
                            T_DNUMBER,
                            T_CONSTANT_ENCAPSED_STRING, 
                            T_DOUBLE_ARROW, 
                            T_CLOSE_TAG,
                            T_NEW,
                            T_DOUBLE_COLON
                            ))) {
                        continue;
                    }


                    exit("For your security, we stoped data parsing at '(" . token_name($type) . ") " . $token[1] . "'.");
                }
            }
        }

        return eval($string);
    }

$a='array(10,20)';
print_r(stringToArray($a));
于 2013-08-12T13:16:20.967 回答
2

使用标记器

function stringToArray($str) {
    $array = array();
    $toks = token_get_all("<?php $str");

    if ($toks[1][0] != T_ARRAY || $toks[2] != '(' || end($toks) != ')')
        return null;

    for($i=3; $i<count($toks)-1; $i+=2) {
        if (count($toks[$i]) != 3)
            return null;

        if ($toks[$i][0] == T_WHITESPACE) {
            $i--;
            continue;
        }

        if ($toks[$i][0] == T_VARIABLE || $toks[$i][0] == T_STRING)
            return null;

        $value = $toks[$i][1];
        if ($toks[$i][0] == T_CONSTANT_ENCAPSED_STRING)
            $value = substr($value, 1, strlen($value) - 2);

        $array[] = $value;

        if ($toks[$i + 1] != ',' && $toks[$i + 1] != ')' && $toks[$i + 1][0] != T_WHITESPACE)
            return null;
    }

    return $array;
}

以上仅适用于文字。传递变量、常量、表达式、嵌套数组或格式错误的数组声明将返回null

stringToArray('array(1,2)');              // works
stringToArray('array(1,2.4)');            // works
stringToArray('array("foo",2)');          // works
stringToArray('array(\'hello\',2)');      // works
stringToArray('array()');                 // works
stringToArray('array(1,2 + 3)');          // returns null
stringToArray('array(1,2 + 3)');          // returns null
stringToArray('array("foo"."bar")');      // returns null
stringToArray('array(array("hello"))');   // returns null
stringToArray('array($a,$b)');            // returns null
stringToArray('array(new bar)');          // returns null
stringToArray('array(SOME_CONST)');       // returns null
stringToArray('hello');                   // returns null

您还可以使用以下内容检查您的字符串是否为数组表达式:

function isArrayExpression($str) {
    $toks = token_get_all("<?php $str");
    return (
        $toks[1][0] == T_ARRAY &&
        $toks[2] == '(' &&
        end($toks) == ')'
    );
}

isArrayExpression('array(1,2,3)');         // true
isArrayExpression('array is cool');        // false
isArrayExpression('array(!!!!');           // false

您可以随时根据需要对其进行调整。希望这可以帮助。

于 2012-06-29T19:18:00.160 回答
0

您可以使用 eval,但我强烈建议不要使用它,而是尝试以更好的方式重新考虑您的设计来处理设置。因此,对于您的示例,而不是存储

'setting' => 'array(50,25)'

你能做类似的事情吗

'setting' => array('type'=>'array', 'value'=>'50, 25')

然后当你加载你可以做的设置

switch($type)
case 'array'
  $val = explode(', ', $value)

或类似的东西

但就像其他人建议的那样,我会尝试使用序列化保存设置

于 2012-06-29T18:57:45.093 回答
0

正如您帖子评论中所建议的那样, eval() 将满足您的需求。但是,首先将数组存储为字符串并不实际。如果您希望使数据更具可移植性,我建议使用json_encode()甚至serialize()

于 2012-06-29T19:01:29.080 回答