curl POST format for CURLOPT_POSTFIELDS

PhpPostCurl

Php Problem Overview


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

for example: 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);

Php Solutions


Solution 1 - Php

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, '', '&');

Solution 2 - Php

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¶2=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);
}

Solution 3 - Php

Do not pass a string at all!

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

Solution 4 - Php

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

Solution 5 - Php

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 ...

Solution 6 - Php

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¶2=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'
]

Solution 7 - Php

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.

Solution 8 - Php

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

Solution 9 - Php

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.

Solution 10 - Php

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKenView Question on Stackoverflow
Solution 1 - PhpkodeartView Answer on Stackoverflow
Solution 2 - PhpCzechnologyView Answer on Stackoverflow
Solution 3 - PhpThiefMasterView Answer on Stackoverflow
Solution 4 - PhpShraddha VadnereView Answer on Stackoverflow
Solution 5 - Php7ochemView Answer on Stackoverflow
Solution 6 - PhpBuzutView Answer on Stackoverflow
Solution 7 - PhpSurreal DreamsView Answer on Stackoverflow
Solution 8 - PhpMaxim RysevetsView Answer on Stackoverflow
Solution 9 - PhpKlompenrunnerView Answer on Stackoverflow
Solution 10 - Phpuser2512571View Answer on Stackoverflow