http_build_query 函数的过度 urlencoding

Des*_*ume 5 php url urlencode query-string

为什么在使用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));
Run Code Online (Sandbox Code Playgroud)

输出:

var%5Bfoo%5D=value&var%5Bbar%5D=encodedBracket%5B
urldecoded: var[foo]=value&var[bar]=encodedBracket[
Run Code Online (Sandbox Code Playgroud)

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

根据第 2.2 节统一资源标识符 (URI) 的保留字符:通用语法

URI 包括由“保留”集中的字符分隔的组件和子组件。这些字符被称为“保留”,因为它们可能(或可能不)被通用语法、每个方案特定的语法或 URI 解引用算法的实现特定的语法定义为定界符。如果 URI 组件的数据与作为分隔符的保留字符的用途发生冲突,则必须在形成 URI 之前对冲突数据进行百分比编码。

保留 = gen-delims / sub-delims

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

子delims =“!” / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="

因此,http_build_query真的不应该[]只在需要的地方使用urlencoded 等字符生成更具可读性的输出吗?我如何让它产生这样的输出?

sro*_*oes 0

我在这里找到了以下“修复” :

[...]我一直在使用的可行的“修复”是使用以下内容对 http_build_query() 输出进行后处理 - 一个“解决方案”,这让我的皮肤有点爬行:

function http_build_query_unborker($s) {
    return preg_replace_callback('#%5[bd](?=[^&]*=)#i', function($match) {
        return urldecode($match[0]); 
    }, $s);
}
Run Code Online (Sandbox Code Playgroud)

所以现在它会变成:

$query = array("var" => array("foo" => "value", "bar" => "encodedBracket["));
$queryString = http_build_query_unborker(http_build_query($query, "", "&"));
var_dump($queryString);
var_dump("urldecoded: " . urldecode($queryString)); // var[foo]=value&var[bar]=encodedBracket%5B
Run Code Online (Sandbox Code Playgroud)