【问题标题】:php url query nested array with no indexphp url查询没有索引的嵌套数组
【发布时间】:2012-08-13 08:35:30
【问题描述】:

我正在使用第三方 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&amp;text[1]=How%20are%20you?&amp;html[0]=&lt;p&gt;Just%20fine,%20thank%20you&lt;/p&gt;

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

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

谢谢

【问题讨论】:

    标签: php arrays function


    【解决方案1】:

    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 以便其他人可以使用它!

    【讨论】:

    • 我修复了您发布的示例,现在它只对[] 进行编码才有效。
    【解决方案2】:

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

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

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

    【讨论】:

    • 想法在这里,但这是正确的实现(参见 php 在线手册的 cmets): preg_replace('/%5B[0-9]+%5D/simU', '%5B%5D ', $http_query);
    • 同意@ErdalG。您还可以执行以下操作:$httpQuery = http_build_query($params, null, '&amp;'); $httpQueryDecoded = urldecode($httpQuery); $requestDataFormatted = urlencode(preg_replace('#\[[\d]+\]#', '[]', $httpQueryDecoded));
    【解决方案3】:

    试试这个:

    $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;
    

    【讨论】:

    • 不仅对空格进行编码,还不如在循环中使用urlencode
    • urlencode 将用 %5B%5D%3D 替换 [] - 根据上面提供的 OP 示例 - 这不是预期的输出。
    • @RiaD 好吧,这就是你的解决方案 :))))
    【解决方案4】:

    我非常同意 RiaD 的回答,但是您可能会在使用此代码时遇到一些问题(抱歉,由于缺乏代表,我不能只发表评论)。

    首先,据我所知http_build_query 返回一个 urlencode() 的字符串,这意味着您不会有 [ 和 ],而是会有 %5B 和 %5D。

    其次,PHP 的 PCRE 引擎将 '[' 字符识别为字符类的开头,而不仅仅是简单的 '[' (PCRE Meta Characters)。这最终可能会用“[]”替换您请求中的所有数字。

    你更可能想要这样的东西:

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

    在这种情况下,您需要转义 % 字符,因为它们也有特殊含义。如果你有一个带有实际括号而不是转义符的字符串,试试这个:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-01-05
      • 2013-06-12
      • 2019-02-20
      • 2015-06-29
      • 2018-11-16
      • 2023-03-05
      • 2021-08-11
      • 1970-01-01
      相关资源
      最近更新 更多