问题
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