PHP - 将多维数组转换为查询字符串

9
搜索了很久,但没有得到任何可行的答案。
A) 输入:
$array = array(
            'order_source' => array('google','facebook'), 
            'order_medium' => 'google-text'
          );


看起来像这样:

Array
(
    [order_source] => Array
        (
            [0] => google
            [1] => facebook
        )

    [order_medium] => google-text
)


B) 需要的输出结果:

order_source=google&order_source=facebook&order_medium=google-text


C) 我尝试过的(http://3v4l.org/b3OYo):

$arr = array('order_source' => array('google','facebook'), 'order_medium' => 'google-text');

function bqs($array, $qs='')
{
    foreach($array as $par => $val)
    {
        if(is_array($val))
        {
            bqs($val, $qs);       
        }
        else
        {
           $qs .= $par.'='.$val.'&';
        }
    }
    return $qs;
}

echo $qss = bqs($arr);


D) 我理解的内容:

order_medium=google-text&


注意:这也适用于任何单维数组,就像http_build_query()一样。


抱歉,但这完全没有意义: order_source=google&order_source=facebook 你正在用第二个覆盖 order_source GET 变量,所以你将得不到第一个?可以运行的方法是:order_source[]=google&order_source[]=facebook - Jared Farrish
不确定您将用它做什么,但因为您提到了 http_build_query,我想提醒一下:order_source=google&order_source=facebook 是行不通的。 - PeeHaa
我来解释一下。这是一个订单管理系统,用户可以点击多个链接,就像Excel表格中的筛选器一样。大概就是这样。 - Parag Tyagi
@JaredFarrish:是的。我知道它会覆盖,因此我已经编写了一个函数,它将整个查询字符串作为输入,并输出一个多维数组。 - Parag Tyagi
为什么?PHP已经将order_status[]=google语法理解为数组了。另外,可能更简单的选项是将您的数组进行JSON编码并将其作为变量传递,然后在服务器上使用json_decode()将其解码回数组。 - Jared Farrish
我曾经使用过类似这样的代码进行转换:https://dev59.com/T3RC5IYBdhLWcg3wRO3k。现在我想要完全相反的效果。 - Parag Tyagi
3个回答

14

我希望这正是你在寻找的,它适用于单维到多维数组。

$walk = function( $item, $key, $parent_key = '' ) use ( &$output, &$walk ) {

    is_array( $item ) 
        ? array_walk( $item, $walk, $key ) 
        : $output[] = http_build_query( array( $parent_key ?: $key => $item ) );

};

array_walk( $array, $walk );

echo implode( '&', $output );  // order_source=google&order_source=facebook&order_medium=google-text 

4

在这里,您实际上不需要做任何特别的事情。

$array = array(
    'order_source' => array('google', 'facebook'),
    'order_medium' => 'google-text'
);
$qss = http_build_query($array);

另一方面:
var_dump($_GET);

结果:

array(2) {
  ["order_source"]=>
  array(2) {
    [0]=>
    string(6) "google"
    [1]=>
    string(8) "facebook"
  }
  ["order_medium"]=>
  string(11) "google-text"
}

这确实是将数组作为GET变量发送的最佳方法。

如果您非常需要按照您定义的方式输出,可以使用以下方法:

function bqs($array, $qs = false) {
    $parts = array();
    if ($qs) {
        $parts[] = $qs;
    }
    foreach ($array as $key => $value) {
        if (is_array($value)) {
            foreach ($value as $value2) {
                $parts[] = http_build_query(array($key => $value2));
            }
        } else {
            $parts[] = http_build_query(array($key => $value));
        }
    }
    return join('&', $parts);
}

如果您想通过POST发送http_build_query结果,则在此之前请对输出进行urldecode()处理;对于GET请求,这一步是不必要的。 - ddruganov

1

虽然正如你在评论中发现的那样,如果你尝试将此作为$_GET传递,你将会遇到覆盖问题。解决你的问题并获得所需结果的方法是使用递归函数:

function bqs($array, $qs='',$index = false)
{
    foreach($array as $par => $val)
    {
        if($index)
            $par = $index;

        if(is_array($val))
        {
            $qs = bqs($val, $qs,$par);       
        }
        else
        {
           $qs .= $par.'='.$val.'&';
        }
    }
    return $qs;
}

我在这里将$qs字符串与数组连接起来,如果它是一个array(),则将索引和值一起传递作为引用。

修改后的代码 在提供$index之后,您不需要再次进行连接。请参见此处:http://3v4l.org/QHF5G


检查修复时,如果是数组,请勿进行连接操作。 - Kypros
仅仅使用key=value是不安全的,因为任何一部分都可能需要编码。这就是http_build_query的作用。 - rjdown

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接