PHP: How to turn a string that contains an array expression in an actual array?

邮差的信 提交于 2019-12-20 04:13:48

问题


I have an array of user inputs ($atts) as key=>value pairs. Some of the values could be written as an array expression, such as:

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

In those cases, I would like to convert the array expression contained in that string into an actual array. So the output would be something like:

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

Written logically, the code would be:

For each key=>value pair in the array $atts... if the value is a string formatted as an array expression... explode that value into an array.

Anybody know how I would write this in PHP?


回答1:


Use the tokenizer:

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;
}

The above will work only for literals. Passing a variable, a constant, an expression, a nested array or a malformed array declaration will return 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

You can also use the following to check if your string is an array expression or not:

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

You can always tweak it to your needs. Hope this helps.




回答2:


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));



回答3:


As suggested in the comments of your post, eval() will do what you're looking for. However it's not really practical to store arrays as strings in the first place. If you're looking to make data more portable, I'd recommend using json_encode() or even serialize()




回答4:


You can use eval, but I would highly recommend not using it, and instead try to rethink your design on a better way to handle the settings. So for your example instead of storing

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

Could you do something like

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

then when you load the settings you can do

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

Or something similar

But like others suggested, I would try to save the settings using serialization



来源:https://stackoverflow.com/questions/11267434/php-how-to-turn-a-string-that-contains-an-array-expression-in-an-actual-array

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!