php 具有相同名称参数的http_build_query

r7knjye2  于 2023-09-29  发布在  PHP
关注(0)|答案(2)|浏览(116)

有没有一种方法可以用http_build_query使用同名参数自动构建查询?
如果我做一些

array('foo' => 'x', 'foo' => 'y');

它们显然在数组中被覆盖,但即使我这样做:

array('foo' => array('x', 'y'));

该函数创建了类似foo[0]=x&foo[1]的东西,这不是我想要的,因为我需要这种格式的参数foo=x&foo=y

pengsaosao

pengsaosao1#

您可以通过对http_build_query()的结果进行替换来解决这个问题,其中[0][1],.,后缀是URL编码的。

$vars = array('foo' => array('x', 'y'));
$query = http_build_query($vars); # foo%5B0%5D=x&foo%5B1%5D=y (URL-encoded foo[0]=x&foo[1]=y)
$query = preg_replace('/%5B\d+%5D(?==)/', '', $query); # foo=x&foo=y

look-ahead((?= … ))确保它只替换名称末尾的值,因为它们后面总是跟着=。PHP不会生成前导零的索引,所以\d+(1位或更多位)足以检测它们。
有些系统要求方括号内没有索引。在这种情况下,您可以使用以下命令:

$query = preg_replace('/(?<=%5B)\d+(?=%5D=)/', '', $query); # foo%5B%5D=x&foo%5B%5D=y (URL-encoded foo[]=x&foo[]=y)
jogvjijk

jogvjijk2#

下面是我创建的一个函数,用于构建查询并保留名称。我创建这个是为了与第三方API一起使用,该API需要具有相同名称的多个查询字符串参数。

function custom_build_query(
    array|object $query_data,
    string $numeric_prefix = "",
    ?string $arg_separator = null,
    int $encoding_type = PHP_QUERY_RFC1738
): string {
    // Cast to array if object is supplied.
    $query_data = is_object($query_data) ? get_object_vars($query_data) : $query_data;
    
    // Use supplied arg_separator value, defaulting to the `arg_separator.output` php configuration.
    $arg_separator = $arg_separator ?? ini_get("arg_separator.output");
    
    // If PHP_QUERY_RFC3986 is specified, use rawurlencode to encode parameters.
    $encoding_function = $encoding_type === PHP_QUERY_RFC3986 ? "rawurlencode" : "urlencode";
    
    $query = [];
    foreach ($query_data as $name => $value) {
        $value = (array) $value;
        $name = is_int($name) ? $numeric_prefix . $name : $name;
        array_walk_recursive($value, function ($value) use (&$query, $name, $encoding_function) {
            $query[] = $encoding_function($name) . "=" . $encoding_function($value);
        });
    }
    return implode($arg_separator, $query);
}

使用方法:

echo custom_build_query(['a' => 1, 'b' => 2, 'c' => [3, 4]]);

输出量:

a=1&b=2&c=3&c=4

注意:该函数的签名与http_build_query完全兼容。当然,唯一的区别是,该函数将不使用括号作为子数组参数。

相关问题