PHP之http_build_query:这个函数好像有点意思有URL请求中生成 URL-encode 之后的请求字符串的实践。

jackxiang 2011-4-27 20:27 | |
当我们使用CURL来post数据的时候,需要设置post的数据
curl_setopt($c, CURLOPT_POSTFIELDS, $post_data);

假如这里的$data是

$data = array(
'name'=>'scofield',
'time'=>'2012-2-3'
)
接下来,需要先将$data变成字符串
$post_data = http_build_query($data);
而采用 http_build_query 转换后再
curl_setopt($c, CURLOPT_POSTFIELDS, $post_data);
看起来没有什么问题。但在实际操作中,$post_data 并没有完全被post过去,user_id丢失了。

解决方法:http_build_query($data,"","&");

附:curl post示例:

来自:http://www.dewen.org/q/1406/http_build_query+%E7%9A%84%E4%B8%80%E4%B8%AA%E9%97%AE%E9%A2%98



http_build_query — 生成 URL-encode 之后的请求字符串
string http_build_query ( array $formdata [, string $numeric_prefix ] )
使用给出的关联(或下标)数组生成一个经过 URL-encode 的请求字符串。参数 formdata 可以是数组或包含属性的对象。一个 formdata 数组可以是简单的一维结构,也可以是由数组组成的数组(其依次可以包含其它数组)。如果在基础数组中使用了数字下标同时给出了 numeric_prefix 参数,此参数值将会作为基础数组中的数字下标元素的前缀。这是为了让 PHP 或其它 CGI 程序在稍后对数据进行解码时获取合法的变量名。

<?php
$data = array('foo'=>'bar',
              'baz'=>'boom',
              'cow'=>'milk',
              'php'=>'hypertext processor');              
echo http_build_query($data); // foo=bar&baz=boom&cow=milk&php=hypertext+processor
?>


<?php
$data = array('foo', 'bar', 'baz', 'boom', 'cow' => 'milk', 'php' =>'hypertext processor');
echo http_build_query($data);
/* 输出:
      0=foo&1=bar&2=baz&3=boom&cow=milk&php=hypertext+processor
*/
echo http_build_query($data, 'myvar_');
/* 输出:
      myvar_0=foo&myvar_1=bar&myvar_2=baz&myvar_3=boom&cow=milk&php=hypertext+processor
*/
?>


<?php
$data = array('user'=>array('name'=>'Bob Smith',
                            'age'=>47,
                            'sex'=>'M',
                            'dob'=>'5/12/1956'),
              'pastimes'=>array('golf', 'opera', 'poker', 'rap'),
              'children'=>array('bobby'=>array('age'=>12,
                                               'sex'=>'M'),
                                'sally'=>array('age'=>8,
                                               'sex'=>'F')),
              'CEO');
echo http_build_query($data, 'flags_');
?>

本例将输出(为可读性进行了折行):
      user[name]=Bob+Smith&user[age]=47&user[sex]=M&user[dob]=5%1F12%1F1956&
      pastimes[0]=golf&pastimes[1]=opera&pastimes[2]=poker&pastimes[3]=rap&
      children[bobby][age]=12&children[bobby][sex]=M&children[sally][age]=8&
      children[sally][sex]=F&flags_0=CEO

<?php
class myClass {
  var $foo;
  var $baz;
  function myClass()
  {
    $this->foo = 'bar';
    $this->baz = 'boom';
  }
}
$data = new myClass();
echo http_build_query($data); // foo=bar&baz=boom
?>


http_build_str:
这个函数有个要求:(PECL pecl_http >= 0.23.0)
string http_build_str ( array $query [, string $prefix [, string $arg_separator = ini_get("arg_separator.output") ]] )
Opponent to parse_str().

特别是对这个字符串 URL-encode 之后的请求字符串的测试如下:

%3C=%3C&%3E=%3E&%22=%22&%27=%27
一)上述程序修改修改,真正提一个经过urlencode后的get请求:

通过tcpdump导出后再通过wireshark查看到其get请求是:
GET /get.php?%3C=%3C&%3E
=%3E&%22=%22&%27=%27 HTTP/1.1..Host: tools.jackxiang.com..Accept: */*....
而返回则是(因为服务端对urlencode编码作了解码后输出,所以又还原原来的字段串了,更加详细内容参看:https://jackxiang.com/post/6954/):
[root@test tmp]# php http_build_query.php
Array
(
    [<] => <
    [>] => >
    ["] => "
    ['] => '
)
PHP接受端:
get.php

Array
(
    [<] => <
    [>] => >
    ["] => "
    ['] => '
)

二)如果不用http_build_query呢?

tcpdump接合wireshark抓包其请求如下:
GET /get.php?<=<&>=>&'=' HTTP/1.1\r\n
Host: tools.jackxiang.com\r\n
Accept: */*\r\n
Full request URI: http://tools.jackxiang.com/get.php?<=<&>=>&'='
返回如下(说明不加urlrewrite的返回也是一样的,这个输入如果不http_build_query的话和服务端处理密切相关,有些接口可能必须要http_build_query下否则会出现逻辑上的接口错误,如:评论,出现不http_build_query也就是不urlencode下,出现插入错误,这都是文档没写名白容易造成的错误。):
返回如下:
Line-based text data: text/html
Array\n
(\n
    [<] => <\n
    [>] => >\n
    ['] => '\n
)\n

作者:jackxiang@向东博客 专注WEB应用 构架之美 --- 构架之美,在于尽态极妍 | 应用之美,在于药到病除
地址:http://jackxiang.com/post/4252/
版权所有。转载时必须以链接形式注明作者和原始出处及本声明!


最后编辑: jackxiang 编辑于2014-9-22 11:06
评论列表
2011-4-28 20:24 | wang Homepage
不错,平时数据都是拼装成url, 都没想到这个方法。下回会用这个了。
分页: 1/1 第一页 1 最后页
发表评论

昵称

网址

电邮

打开HTML 打开UBB 打开表情 隐藏 记住我 [登入] [注册]