卷曲CURLOPT_POSTFIELDS的POST格式


99

当我使用curlvia POST和set时CURLOPT_POSTFIELD,我必须是to urlencode还是任何特殊格式?

例如:如果我要发布2个字段,则第一个和最后一个:

first=John&last=Smith

curl应该使用的确切代码/格式是什么?

$ch=curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$reply=curl_exec($ch);
curl_close($ch);

Answers:


100

如果您要发送字符串,请使用urlencode()。否则,如果为数组,则应为key => value配对,并且Content-type标头会自动设置为multipart/form-data

另外,您不必创建额外的函数即可为数组构建查询,您已经拥有了:

$query = http_build_query($data, '', '&');

13
您可以使用,http_build_query($data)因为&它是默认的分隔符。
nullability,2014年

6
当然,您可以跳过它们。这是为了说明您可以(也可以不)更改(例如默认分隔符)以满足您的特定需求的其他两个参数。
kodeart 2014年

62

编辑:从php5起,http_build_query建议使用:

string http_build_query ( mixed $query_data [, string $numeric_prefix [, 
                          string $arg_separator [, int $enc_type = PHP_QUERY_RFC1738 ]]] )

手册中的简单示例:

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

echo http_build_query($data) . "\n";

/* output:
foo=bar&baz=boom&cow=milk&php=hypertext+processor
*/

?>

在php5之前:

手册

CURLOPT_POSTFIELDS

要在HTTP“ POST”操作中发布的完整数据。要发布文件,请在文件名前添加@并使用完整路径。可以通过在文件名后跟随类型'; type = mimetype'的类型来明确指定文件类型。此参数可以作为urlencoded字符串(如“ para1 = val1&para2 = val2&...”)传递,也可以作为字段名称为键且字段数据为值的数组传递。如果value是一个数组,则Content-Type标头将设置为multipart / form-data。从PHP 5.2.0开始,使用@前缀传递给此选项的文件必须采用数组形式才能工作。

因此,类似这样的事情应该可以很好地工作(通过关联数组传递参数):

function preparePostFields($array) {
  $params = array();

  foreach ($array as $key => $value) {
    $params[] = $key . '=' . urlencode($value);
  }

  return implode('&', $params);
}

11
如果可以传递数组,为什么还要传递字符串...?
ThiefMaster 2011年

1
我认为$ key也应该编码,以防万一,例如“ name&surname”等。特别是如果数据是由最终用户提供的
MariusBalčytis2012年

2
@barius,我同意你的看法。而且我认为http_build_query()实际上比上面定义的功能更好。
2014年

1
@skyfree我同意!该功能已添加到php5中,尽管它在2011
仍不

1
为什么只需传递数组就需要http_build_query?
Offenso

39

根本不要传递字符串!

您可以传递一个数组,让php / curl完成编码等工作。


16
传递数组将是与字符串不同的Content-type,因此这样做是有充分理由的。花了我一段时间才能弄清楚。
Thomas Vander Stichele,2012年

我不知道为什么,但是我发现在我的win dev个人电脑上,通过数组需要花费大约一秒钟的时间(使用数组的时间为1.029s,而使用http_build_query()同一数组的时间为0.016s )
kratenko 2015年

2
嵌套数组将不起作用。cURL将尝试将它们转换为字符串,然后将出现PHP Array到字符串转换的通知
7ochem


4

对于CURLOPT_POSTFIELDS,参数可以像urlencoded字符串一样传递,也可以作为para1=val1&para2=val2&..字段名称为键,字段数据为值的数组传递

尝试以下格式:

$data = json_encode(array(
"first"  => "John",
"last" => "Smith"
));

$ch = curl_init(); 
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$output = curl_exec($ch);
curl_close($ch);

2
您好Shraddha,json_encode()会为您提供与有效参数字符串完全不同的东西,例如first=John&last=Smithjson_encode()将输出:{"first":"John","last":"Smith"}这将成为POST请求的原始内容。
7ochem '18年

1
要添加到@ 7ochem的注释中:除非收件人期望包含json编码的字符串的单个参数json_encode(...)否则不要使用do http_build_query(...)。这将创建预期的“ URL编码的字符串”,其中包含用“&”分隔的参数。
ToolmakerSteve

4

这里尚未提及的另一个主要区别是CURLOPT_POSTFIELDS不能处理嵌套数组。

如果我们使用嵌套数组,['a' => 1, 'b' => [2, 3, 4]]则应将其参数化为a=1&b[]=2&b[]=3&b[]=4[]将/应该被URL编码)。这将自动转换回另一端的嵌套数组(假设另一端也是PHP)。

这将起作用:

var_dump(http_build_query(['a' => 1, 'b' => [2, 3, 4]]));
// output: string(36) "a=1&b%5B0%5D=2&b%5B1%5D=3&b%5B2%5D=4"

这行不通:

curl_setopt($ch, CURLOPT_POSTFIELDS, ['a' => 1, 'b' => [2, 3, 4]]);

这会给您通知。代码执行将继续,并且您的端点将接收b字符串形式的参数"Array"

PHP注意:在线...上的数组到字符串的转换...


4

这取决于 content-type

网址编码或多部分/表单数据

要以标准方式发送数据,就像浏览器使用表单一样,只需传递一个关联数组即可。如PHP手册所述:

此参数可以作为urlencoded字符串(如“ para1 = val1&para2 = val2&...”)传递,也可以作为字段名称为键且字段数据为值的数组传递。如果value是一个数组,则Content-Type标头将设置为multipart / form-data。

JSON编码

不过,在与JSON API通信时,必须对API内容进行JSON编码才能理解我们的POST数据。

在这种情况下,必须将内容显式编码为JSON:

CURLOPT_POSTFIELDS => json_encode(['param1' => $param1, 'param2' => $param2]),

当使用JSON进行通信时,我们通常还会相应地设置acceptcontent-type标头:

CURLOPT_HTTPHEADER => [
    'accept: application/json',
    'content-type: application/json'
]


0

有趣的是Postman进行 POST 的方式是使用以下2个附加选项的完整GET操作:

curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_POSTFIELDS, '');

只是另一种方式,而且效果很好。


-3

这个答案也使我永远找到了。我发现您所要做的就是将URL(文件名和扩展名后面的'?')与URL编码的查询字符串连接在一起。看起来甚至不必设置POST cURL选项。请参见下面的伪造示例:

//create URL
$exampleURL = 'http://www.example.com/example.php?';

// create curl resource
$ch = curl_init(); 

// build URL-encoded query string
$data = http_build_query(
    array('first' => 'John', 'last' => 'Smith', '&'); // set url
curl_setopt($ch, CURLOPT_URL, $exampleURL . $data); 

// return the transfer as a string
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 

// $output contains the output string
$output = curl_exec($ch); 

// close curl resource to free up system resources <br/>
curl_close($ch);

您也可以使用file_get_contents()

// read entire webpage file into a string
$output = file_get_contents($exampleURL . $data);

9
似乎您正在执行GET而不是POST。
2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.