php - http_build_query 函数的 urlencoding 过多

标签 php url query-string urlencode

为什么在使用 http_build_query 函数构建查询字符串时,它会将方括号 [] urlencode 到值之外,如何摆脱它?

$query = array("var" => array("foo" => "value", "bar" => "encodedBracket["));
$queryString = http_build_query($query, "", "&");
var_dump($queryString);
var_dump("urldecoded: " . urldecode($queryString));

输出:

var%5Bfoo%5D=value&var%5Bbar%5D=encodedBracket%5B
urldecoded: var[foo]=value&var[bar]=encodedBracket[

该函数在输出第一行的 encodedBracket[ 中正确地对 [ 进行了 urlencode,但是在 var[foo] 中对方括号进行编码的原因是什么=var[bar]=?如您所见,对字符串进行 urldecoding 还对值中的保留字符进行解码,encodedBracket%5B 应该保持原样以使查询字符串正确,而不是变成 encodedBracket[

根据 section 2.2 Reserved Characters of Uniform Resource Identifier (URI): Generic Syntax

URIs include components and subcomponents that are delimited by characters in the "reserved" set. These characters are called "reserved" because they may (or may not) be defined as delimiters by the generic syntax, by each scheme-specific syntax, or by the implementation-specific syntax of a URI's dereferencing algorithm. If data for a URI component would conflict with a reserved character's purpose as a delimiter, then the conflicting data must be percent-encoded before the URI is formed.

reserved = gen-delims / sub-delims

gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"

sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="

那么 http_build_query 真的不应该产生更具可读性的输出吗?像 [] 这样的字符只在需要的地方进行 urlencode 编码?我如何让它产生这样的输出?

最佳答案

这是我编写的一个快速函数,用于生成更好的查询字符串。它不仅不对方括号进行编码,而且如果与索引匹配,还会省略数组键。 请注意,它不支持对象或 http_build_query 的附加选项。 $prefix 参数用于递归,在初始调用时应省略。

function http_clean_query(array $query_data, string $prefix=null): string {
    $parts = [];
    $i = 0;
    foreach ($query_data as $key=>$value) {
        if ($prefix === null) {
            $key = rawurlencode($key);
        } else if ($key === $i) {
            $key = $prefix.'[]';
            $i++;
        } else {
            $key = $prefix.'['.rawurlencode($key).']';
        }
        if (is_array($value)) {
            if (!empty($value)) $parts[] = http_clean_query($value, $key);
        } else {
            $parts[] = $key.'='.rawurlencode($value);
        }
    }
    return implode('&', $parts);
}

关于php - http_build_query 函数的 urlencoding 过多,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21046623/

相关文章:

php - 使用while循环创建php多维数组

url - Node : Redirect URL

url - Artifactory 通过文件系统更改基本 URL

javascript - axios + 查询字符串与 jQuery,POST 数据被查询字符串破坏

php - 使用查询字符串中的变量获取数据?

php - 从 MYSQL 读取时只显示 $_SESSION ["ID"];

php - "Notice: Undefined variable"、 "Notice: Undefined index"、 "Warning: Undefined array key"和 "Notice: Undefined offset"使用 PHP

twitter-bootstrap - 出于 SEO 原因,如何通过 url 访问 Bootstrap 模式

javascript - 以 utm 字符串传递电子邮件

PHP PDO lastInsertId() 函数混淆