CURLOPT_POSTFIELDS 的 curl POST 格式

当我使用 curl通过 POST和设置 CURLOPT_POSTFIELD我必须 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);
326141 次浏览

根据 PHP 手册,以字符串形式传递给 cURL 的数据应该是 URLencode。请参见有关 Curl _ setopt ()的页面并搜索 CURLOPT_POSTFIELDS

编辑 : 从 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
*/


?>

before php5:

来自 手动操作:

CURLOPT _ POSTFIELDS

要在 HTTP“ POST”操作中发布的完整数据。要发布文件,请在文件名前面加上@并使用完整路径。可以通过在文件名后面显式指定格式为“ ; type = imetype”的文件类型。从 PHP 5.2.0开始,传递给@前缀选项的文件必须采用数组形式才能工作。

所以像这样的东西应该能够很好地工作(通过在关联数组中传递参数) :

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


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


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

如果要发送字符串,请对其进行 urlencode ()。否则,如果是数组,它应该是键 = > 值配对,并且 Content-type头自动设置为 multipart/form-data

此外,您不必创建额外的函数来构建数组的查询,您已经具备了:

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

根本不要传绳子!

你可以传递一个数组,让 php/curl 来完成编码等繁琐的工作。

我也花了很长时间才找到这个答案。我发现你所要做的就是连接 URL (’?’)在文件名和扩展名之后) ,使用 URL 编码的查询字符串。看起来甚至不需要设置 POSTcURL 选项。看看下面这个假的例子:

//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);

对于 CURLOPT_POSTFIELDS,参数可以作为 urlencode 字符串(如 para1=val1&para2=val2&..)传递,也可以作为字段名作为键、字段数据作为值的数组传递

Try the following format :

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

这里还没有提到的另一个主要区别是 CURLOPT_POSTFIELDS不能处理嵌套数组。

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

This will work:

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 注意: 数组到字符串的转换... 在线..。

当我们为 CMS Effcore 编写测试时,我们正在寻找相同的解决方案。解决办法非常简单,如下所示:

$data = [
'name[0]' => 'value 1',
'name[1]' => 'value 2',
'name[2]' => 'value 3',
'id'      => 'value 4'
];


$data = array(
'name[0]' => 'value 1',
'name[1]' => 'value 2',
'name[2]' => 'value 3',
'id'      => 'value 4'
);

Interestingly the way 邮差 does POST is a complete GET operation with these 2 additional options:

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

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

这取决于 content-type

Url 编码或多部分/表单数据

要以标准方式发送数据,就像浏览器使用表单一样,只需要 传个关联数组:

这个参数可以作为 urlencode 字符串(如‘ para1 = val1 & para2 = val2 & ...’)传递,也可以作为字段名作为键、字段数据作为值的数组传递。如果 value 是一个数组,Content-Type 头将被设置为 multipart/form-data。

JSON 编码

尽管如此,在与 JSON API 通信时,API 必须对内容进行 JSON 编码,以便理解 POST 数据。

In such cases, content must be explicitely encoded as JSON :

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

在 JSON 进行通信时,我们通常也会相应地设置 acceptcontent-type报头:

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