Php 从URL解析嵌套数组

Php 从URL解析嵌套数组,php,arrays,Php,Arrays,有一个URL参数:- /name/Aario/gender/male/addr[nation][key][sx]/China/addr[city]/Shanghai您可以注意到,有两个类似数组的字符串。我想把它们转换成数组['addr'=>['nation'=>['key'=>['sx'=>China]],['city'=>'Shanghai']] 我试过:- $results = []; $str = '/name/Aario/gender/male/addr[nation][key]

有一个URL参数:-

/name/Aario/gender/male/addr[nation][key][sx]/China/addr[city]/Shanghai


您可以注意到,有两个类似数组的字符串。我想把它们转换成数组
['addr'=>['nation'=>['key'=>['sx'=>China]],['city'=>'Shanghai']]


我试过:-

    $results = [];
$str = '/name/Aario/gender/male/addr[nation][key][sx]/China/addr[city]/Shanghai/';
$params = explode('/', $str);
if($params[0] == '') unset($params[0]);
while(key($params) !== null && current($params)) {
    $key = current($params);
    $value = next($params);
    if(strpos($key, '[')) {
        $sub_keys = explode('[', $key);
        foreach($sub_keys as &$sub_key) {
            $sub_key = trim($sub_key, ']');
        }

        $count = count($sub_keys);
        $ref = &$results;
        foreach($sub_keys as $k => $v) {
            if($k == $count - 1) {
                $ref[$v] = $value;
                $ref = &$ref[$v];
            } else {
                $ref[$v] = $ref[$v] ?? [];
                $ref = &$ref[$v];
            }
        }
    } else {
        $results[$key] = $value;
    }
    next($params);
}
var_dump($results);
它起作用了。它得到:

array(3) { 
    ["name"]=> string(5) "Aario" 
    ["gender"]=> string(4) "male" 
    ["addr"]=> array(2) { 
        ["nation"]=> array(1) { 
            ["key"]=> array(1) { 
                ["sx"]=> string(5) "China" 
            } 
        } 
        ["city"]=> &string(8) "Shanghai"      // please notice here
    } 
}
但我担心参考(
&
)会出错


有更好的方法吗?

一些简单的正则表达式处理:

$replacements = [
    'addr' => [
        'nation' => [
            'key' => [
                'sx' => 'China'
            ]
        ],
        'city' => 'Shanghai'
    ]
];

$url = '/name/Aario/gender/male/addr[nation][key][sx]/China/addr[city]/Shanghai';

$result = preg_replace_callback('~[^/]+~', function (array $match) use ($replacements) {
    if (preg_match_all('/\w+/', $match[0], $keys) > 1) {
        return array_reduce($keys[0], function ($a, $k) { return $a[$k]; }, $replacements);
    } else {
        return $match[0];
    }
}, $url);

var_dump($result);

请注意,我更改了您的
$replacements
数据,因为它与URL中的占位符不对应。

尝试使用递归函数

$str = '/name/Aario/gender/male/addr[nation][key][sx]/China/addr[city]/Shanghai/';
$params = explode('/', $str);
if($params[0] == '') unset($params[0]);


$is_odd_pos = true;
$results = [];

function rec(&$array, $keys, $val){
    $keys = array_values($keys);

    if(count($keys) > 1){
        $key = $keys[0];
        if(!isset($array[$key]))
            $array[$key] = [];

        rec($array[$key], array_slice($keys, 1), $val);
        return;
    }

    $array[$keys[0]] = $val;
}

foreach($params as $k => $value) {
    if($k % 2 == 0){
        $key = $params[$k - 1];
        preg_match_all('/\[(\w+)\]/', $key, $matches);
        if(count($matches[1]) == 0){
            $results[$key] = $value;
            continue;
        }
        $key = explode('[', $key, 2)[0];
        if(!isset($results[$key]))
            $results[$key] = [];

        rec($results[$key], $matches[1], $value);
    }
}

var_dump($results);

将其转换为查询字符串应生成简短的代码:

$str = '/name/Aario/gender/male/addr[nation][key][sx]/China/addr[city]/Shanghai/';
$query = array_reduce(
    array_chunk(explode('/', trim($str, '/')), 2),
    function ($string, $item) {
        return $string . $item[0] . (isset($item[1]) ? '=' . $item[1] : '') . '&';
    }
);

parse_str($query, $result);

您需要更改获取此类url的链接结构。更简单正确的工作。这只是一种特殊的需要……
$str = '/name/Aario/gender/male/addr[nation][key][sx]/China/addr[city]/Shanghai/';
$query = array_reduce(
    array_chunk(explode('/', trim($str, '/')), 2),
    function ($string, $item) {
        return $string . $item[0] . (isset($item[1]) ? '=' . $item[1] : '') . '&';
    }
);

parse_str($query, $result);