This can be useful for example to extract the elements from an enum in PHP using a SHOW COLUMNS
.
In that case decode_list_json
would be the most appropiate since, generally, elements from an
enum and a set do not contain quotes.
// Slow but safe and without side-effects.
function decode_list_preg($list_string) {
preg_match_all("@(?:,|^)('|\")((?:\\\\'|\\\\\\\\|[^'])*)\\1@Umsi", $list_string, $matches);
return array_map('stripslashes', $matches[2]);
}
// Fast but unsafe with the possibility of code injection with an invalid input.
function decode_list_eval($list_string) {
eval('$list = array(' . $list_string . ');');
return $list;
}
// Fast but with side-effects: it changes single quotes with double quotes so it is a valid JSON.
function decode_list_json($list_string) {
return json_decode('[' . str_replace("'", '"', $list_string) . ']');
}
// Slow and safe using PHP's tokenizer.
function decode_list_php($list_string) {
$tokens = array_slice(token_get_all('<?php ' . $list_string), 1);
$expect_comma = false;
$list = array();
//print_r($tokens);
foreach ($tokens as $token) {
if (!is_array($token)) $token = array(0, $token, -1);
if ($expect_comma) {
if ($token[1] !== ',') throw(new Exception("Invalid input (" . token_name($token[0]) . ")"));
} else {
if ($token[0] !== T_CONSTANT_ENCAPSED_STRING) throw(new Exception("Invalid input (" . token_name($token[0]) . ")"));
$list[] = stripslashes(substr($token[1], 1, -1));
}
$expect_comma = !$expect_comma;
}
return $list;
}
function util_rand_string($len) {
$str = '';
while ($len-- > 0) $str .= chr(mt_rand(0x20, 0x7e));
return $str;
}
$str_list = array();
for ($n = 0, $len = mt_rand(1000, 2000); $n < $len; $n++) $str_list[] = var_export(util_rand_string(mt_rand(40, 80)), true);
$list_string = implode(',', $str_list);
//echo $list_string; exit;
//$list_string = "'ho\'la',\"esto\",'es','una','prueba'";
//print_r(decode_list_preg($list_string));
//print_r(decode_list_eval($list_string));
//print_r(decode_list_json($list_string));
print_r(decode_list_php($list_string));
Spanish
Esto puede ser útil por ejemplo para extraer los elementos de un enum en PHP usando un SHOW COLUMNS. En ese caso el decode_list_json podría ser el más apropiado ya que, generalmente, los elementos de un enum o un set no contendrán comillas.
// Lenta pero segura y sin efectos colaterales (en principio).
function decode_list_preg($list_string) {
preg_match_all("@(?:,|^)('|\")((?:\\\\'|\\\\\\\\|[^'])*)\\1@Umsi", $list_string, $matches);
return array_map('stripslashes', $matches[2]);
}
// Rápida pero insegura con posibilidad de inyección de código con una entrada inválida.
function decode_list_eval($list_string) {
eval('$list = array(' . $list_string . ');');
return $list;
}
// Rápida pero con efectos colaterales: cambia comillas simples por dobles para que sea un json válido.
function decode_list_json($list_string) {
return json_decode('[' . str_replace("'", '"', $list_string) . ']');
}
// Lenta y segura usando el tokenizer de php.
function decode_list_php($list_string) {
$tokens = array_slice(token_get_all('<?php ' . $list_string), 1);
$expect_comma = false;
$list = array();
//print_r($tokens);
foreach ($tokens as $token) {
if (!is_array($token)) $token = array(0, $token, -1);
if ($expect_comma) {
if ($token[1] !== ',') throw(new Exception("Invalid input (" . token_name($token[0]) . ")"));
} else {
if ($token[0] !== T_CONSTANT_ENCAPSED_STRING) throw(new Exception("Invalid input (" . token_name($token[0]) . ")"));
$list[] = stripslashes(substr($token[1], 1, -1));
}
$expect_comma = !$expect_comma;
}
return $list;
}
function util_rand_string($len) {
$str = '';
while ($len-- > 0) $str .= chr(mt_rand(0x20, 0x7e));
return $str;
}
$str_list = array();
for ($n = 0, $len = mt_rand(1000, 2000); $n < $len; $n++) $str_list[] = var_export(util_rand_string(mt_rand(40, 80)), true);
$list_string = implode(',', $str_list);
//echo $list_string; exit;
//$list_string = "'ho\'la',\"esto\",'es','una','prueba'";
//print_r(decode_list_preg($list_string));
//print_r(decode_list_eval($list_string));
//print_r(decode_list_json($list_string));
print_r(decode_list_php($list_string));