繁体   English   中英

CURLOPT_POSTFIELDS 的 curl POST 格式

[英]curl POST format for CURLOPT_POSTFIELDS

当我通过POST使用curl并设置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);

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

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

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

编辑:从 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);
}

根本不要传递字符串!

你可以传递一个数组,让 php/curl 做编码等肮脏的工作。

此处尚未提及的另一个主要区别是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 注意:数组到字符串的转换 in ... 在线 ...

对于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);

根据 PHP 手册,作为字符串传递给 cURL 的数据应该进行 URLencoded。 请参阅curl_setopt()页面并搜索CURLOPT_POSTFIELDS

这取决于content-type

url-encoded 或 multipart/form-data

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

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

JSON 编码

尽管如此,在与 JSON API 通信时,内容必须是 JSON 编码的 API 才能理解我们的 POST 数据。

在这种情况下,内容必须明确编码为 JSON :

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

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

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

对于嵌套数组,您可以使用:

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

有趣的是, Postman执行 POST 的方式是一个完整的 GET 操作,带有这两个附加选项:

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

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

这个答案也花了我很长时间才找到。 我发现您所要做的就是将 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);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM