开发者

curl POST format for CURLOPT_POSTFIELDS

When I use curl via POST and set CURLOPT_POSTFIELD do I have to urlencode or any special format?

for exam开发者_Python百科ple: If I want to post 2 fields, first and last:

first=John&last=Smith

what is the exact code/format that should be used with 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);


In case you are sending a string, urlencode() it. Otherwise if array, it should be key=>value paired and the Content-type header is automatically set to multipart/form-data.

Also, you don't have to create extra functions to build the query for your arrays, you already have that:

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


EDIT: From php5 upwards, usage of http_build_query is recommended:

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

Simple example from the manual:

<?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:

From the manual:

CURLOPT_POSTFIELDS

The full data to post in a HTTP "POST" operation. To post a file, prepend a filename with @ and use the full path. The filetype can be explicitly specified by following the filename with the type in the format ';type=mimetype'. This parameter can either be passed as a urlencoded string like 'para1=val1&para2=val2&...' or as an array with the field name as key and field data as value. If value is an array, the Content-Type header will be set to multipart/form-data. As of PHP 5.2.0, files thats passed to this option with the @ prefix must be in array form to work.

So something like this should work perfectly (with parameters passed in a associative array):

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

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

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


Do not pass a string at all!

You can pass an array and let php/curl do the dirty work of encoding etc.


It depends on the content-type

url-encoded or multipart/form-data

To send data the standard way, as a browser would with a form, just pass an associative array. As stated by PHP's manual:

This parameter can either be passed as a urlencoded string like 'para1=val1&para2=val2&...' or as an array with the field name as key and field data as value. If value is an array, the Content-Type header will be set to multipart/form-data.

JSON encoding

Neverthless, when communicating with JSON APIs, content must be JSON encoded for the API to understand our POST data.

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

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

When communicating in JSON, we also usually set accept and content-type headers accordingly:

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


For CURLOPT_POSTFIELDS, the parameters can either be passed as a urlencoded string like para1=val1&para2=val2&.. or as an array with the field name as key and field data as value

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


One other major difference that is not yet mentioned here is that CURLOPT_POSTFIELDS can't handle nested arrays.

If we take the nested array ['a' => 1, 'b' => [2, 3, 4]] then this should be be parameterized as a=1&b[]=2&b[]=3&b[]=4 (the [ and ] will be/should be URL encoded). This will be converted back automatically into a nested array on the other end (assuming here the other end is also 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"

This won't work:

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

This will give you a notice. Code execution will continue and your endpoint will receive parameter b as string "Array":

PHP Notice: Array to string conversion in ... on line ...


According to the PHP manual, data passed to cURL as a string should be URLencoded. See the page for curl_setopt() and search for CURLOPT_POSTFIELDS.


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

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

Just another way, and it works very well.


We were looking for the same solution when we wrote a test for CMS Effcore. The solution turned out to be quite simple and it is shown below:

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


This answer took me forever to find as well. I discovered that all you have to do is concatenate the URL ('?' after the file name and extension) with the URL-encoded query string. It doesn't even look like you have to set the POST cURL options. See the fake example below:

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

You can also use file_get_contents():

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜