PHP中没有索引的嵌套数组的URL查询

15

我正在使用一个第三方API,该API接收多个参数,这些参数必须按照以下方式进行编码:

text[]=Hello%20World&text[]=How%20are%20you?&html[]=<p>Just%20fine,%20thank%20you</p>

你可以看到这个API可以接受多个文本参数,以及HTML参数(在示例调用中未涉及)。

我使用http_build_query来正确构建其他API的查询字符串。

$params['text'][] = 'Hello World';
$params['text'][] = 'How are you?';
$params['html'][] = '<p>Just fine, thank you</p>';

$http_query = http_build_query($params);

这种方法的问题在于它会使用数字索引来构建查询字符串:

text[0]=Hello%20World&text[1]=How%20are%20you?&html[0]=<p>Just%20fine,%20thank%20you</p>

不幸的是,我正在使用的API不喜欢数字索引并失败了。

是否有任何PHP函数/类方法可以帮助我快速构建这样的查询?

谢谢

4个回答

12

我不知道有标准的方法可以做到这一点(我认为没有这样的方法),但这里有一个丑陋的解决方案:

由于[]http_build_query编码,因此您可以生成带有索引的字符串,然后替换它们。

preg_replace('/(%5B)\d+(%5D=)/i', '$1$2', http_build_query($params));

8
这里的想法已经存在,但这是正确的实现(参考PHP在线手册的评论): preg_replace('/%5B[0-9]+%5D/simU', '%5B%5D', $http_query)。 - Erdal G.
同意 @ErdalG。你也可以执行以下操作:$httpQuery = http_build_query($params, null, '&'); $httpQueryDecoded = urldecode($httpQuery); $requestDataFormatted = urlencode(preg_replace('#\[[\d]+\]#', '[]', $httpQueryDecoded)); - Matt

5

我非常赞同RiaD的回答,但你可能会遇到一些问题(很抱歉由于声望不足无法发表评论)。

首先,据我所知http_build_query返回一个被urlencode()处理过的字符串,这意味着你将不会得到[和],而是%5B和%5D。

其次,PHP的PCRE引擎将‘[’字符识别为字符类的开头而不仅仅是一个简单的‘[’ (PCRE元字符)。这可能会导致用'[]'替换请求中的所有数字。

你更有可能需要像下面这样的代码:

preg_replace('/\%5B\d+\%5D/', '%5B%5D', http_build_query($params));

在这种情况下,您需要转义百分号(%),因为它们也具有特殊含义。如果您拥有一个实际括号的字符串而不是转义字符,请尝试以下操作:

preg_replace('/\[\d+\]/', '[]', $http_query);

4

使用http_build_query似乎没有办法做到这一点。抱歉。但在文档页面上,有人提供了以下方法:

function cr_post($a,$b=0,$c=0){
    if (!is_array($a)) return false;
    foreach ((array)$a as $k=>$v){
        if ($c) $k=$b."[]"; elseif (is_int($k)) $k=$b.$k;
        if (is_array($v)||is_object($v)) {
            $r[]=cr_post($v,$k,1);continue;
        }
        $r[]=urlencode($k)."=" .urlencode($v);    
    }
    return implode("&",$r);
}


$params['text'][] = 'Hello World';
$params['text'][] = 'How are you?';
$params['html'][] = '<p>Just fine, thank you</p>';

$str = cr_post($params);
echo $str;

我还没有测试过它。如果不起作用,那么你就需要自己编写代码。也许你可以发布到Github Gist,以便其他人使用!


我修复了你发布的示例,现在它可以工作了,只是它也编码了 [] - Nir Alfasi

1

试试这个:

$params['text'][] = 'Hello World';
$params['text'][] = 'How are you?';
$params['html'][] = '<p>Just fine, thank you</p>';
foreach ($params as $key => $value) {
    foreach ($value as $key2 => $value2) {        
        $http_query.= $key . "[]=" . $value2 . "&";
    }
}
$http_query = substr($http_query, 0, strlen($http_query)-1); // remove the last '&'
$http_query = str_replace(" ", "%20", $http_query); // manually encode spaces
echo $http_query;

1
不仅空格需要编码,最好在循环中使用urlencode。 - RiaD
1
urlencode会将[]替换为%5B%5D%3D,根据上面提供的示例,这不是预期的输出。 - Nir Alfasi
@RiaD 好的,那就是你的解决方案 :)))) - Nir Alfasi

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