curl format POST untuk CURLOPT_POSTFIELDS

99

Ketika saya menggunakan curlvia POSTdan set, CURLOPT_POSTFIELDapakah saya harus urlencodeatau format khusus lainnya?

misalnya: Jika saya ingin memposting 2 bidang, pertama dan terakhir:

first=John&last=Smith

apa kode / format persis yang harus digunakan dengan 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);
Ken
sumber

Jawaban:

100

Jika Anda mengirim string, urlencode () itu. Jika tidak, jika array, itu harus key => value paired dan Content-typeheader secara otomatis diatur ke multipart/form-data.

Selain itu, Anda tidak perlu membuat fungsi tambahan untuk membuat kueri untuk array Anda, Anda sudah memiliki itu:

$query = http_build_query($data, '', '&');
kodeart
sumber
13
Anda bisa menggunakan http_build_query($data)karena &pemisah default.
nullability
6
Tentu saja Anda bisa melewatkannya. Ini untuk mengilustrasikan dua argumen lainnya yang mungkin (atau tidak) Anda ubah (mis. Pemisah default) untuk menyesuaikan dengan kebutuhan spesifik Anda.
kodeart
62

EDIT : Dari php5 ke atas, penggunaan http_build_querydirekomendasikan:

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

Contoh sederhana dari 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
*/

?>

sebelum php5:

Dari manual :

CURLOPT_POSTFIELDS

Data lengkap untuk diposting dalam operasi HTTP "POST". Untuk memposting file, tambahkan nama file dengan @ dan gunakan jalur lengkap. Jenis file dapat ditentukan secara eksplisit dengan mengikuti nama file dengan tipe dalam format '; type = mimetype'. Parameter ini dapat dikirimkan sebagai string yang dikodekan url seperti 'para1 = val1 & para2 = val2 & ...' atau sebagai larik dengan nama bidang sebagai kunci dan data bidang sebagai nilai. Jika nilainya adalah larik, header Tipe Konten akan disetel ke multipart / form-data. Mulai dari PHP 5.2.0, file yang diteruskan ke opsi ini dengan awalan @ harus dalam bentuk array agar dapat berfungsi.

Jadi sesuatu seperti ini harus bekerja dengan sempurna (dengan parameter yang diteruskan dalam array asosiatif):

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

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

  return implode('&', $params);
}
Czechnology
sumber
11
Mengapa Anda melewatkan string jika Anda dapat melewati array ...?
ThiefMaster
1
Saya pikir $ key juga harus dikodekan, kalau-kalau Anda memilikinya seperti "nama & nama keluarga" dll. Terutama jika data diberikan oleh pengguna akhir
Marius Balčytis
2
@barius, saya setuju dengan Anda. Dan menurut saya http_build_query () sebenarnya lebih baik daripada fungsi yang didefinisikan di atas.
skyfree
1
@skyfree Saya setuju! Fungsi itu ditambahkan dalam php5 meskipun masih jauh dari standar pada tahun 2011.
Czechnology
1
mengapa http_build_query diperlukan ketika Anda bisa meneruskan array?
Offenso
39

Jangan berikan string sama sekali!

Anda dapat meneruskan sebuah array dan membiarkan php / curl melakukan pekerjaan kotor encoding, dll.

ThiefMaster
sumber
16
meneruskan sebuah array akan menjadi tipe konten yang berbeda dari string, jadi ada alasan bagus untuk melakukannya. Butuh beberapa saat untuk mencari tahu.
Thomas Vander Stichele
Saya tidak tahu mengapa, tetapi saya menemukan bahwa pada win dev pc saya melewati array membutuhkan waktu sekitar satu detik lebih lama (1.029s menggunakan array vs. 0.016s menggunakan http_build_query()array yang sama)
kratenko
2
Array bersarang tidak akan berfungsi. cURL akan mencoba mengubahnya menjadi string dan pemberitahuan konversi Array PHP menjadi string akan mengikuti
7ochem
5

Menurut manual PHP, data yang diteruskan ke cURL sebagai string harus dienkode URL. Lihat halaman curl_setopt () dan cari CURLOPT_POSTFIELDS.

Mimpi yang Nyata
sumber
4

Karena CURLOPT_POSTFIELDS, parameter dapat dikirimkan sebagai string yang di-urlencode seperti para1=val1&para2=val2&..atau sebagai array dengan nama bidang sebagai kunci dan data bidang sebagai nilai

Coba format berikut:

$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);
Shraddha Vadnere
sumber
2
Halo Shraddha, json_encode()akan memberi Anda sesuatu yang sangat berbeda dari string parameter yang valid sebagai first=John&last=Smith. json_encode()akan menampilkan: {"first":"John","last":"Smith"}yang kemudian akan menjadi badan mentah permintaan POST Anda.
7ochem
1
Untuk menambahkan ke komentar @ 7ochem: Kecuali jika penerima mengharapkan parameter tunggal yang berisi string berenkode-json , bukan json_encode(...)do http_build_query(...). Ini akan membuat "string berenkode url" yang diharapkan berisi parameter yang dipisahkan oleh "&".
ToolmakerSteve
4

Satu perbedaan utama lainnya yang belum disebutkan di sini adalah CURLOPT_POSTFIELDStidak dapat menangani array bersarang.

Jika kita mengambil array bersarang ['a' => 1, 'b' => [2, 3, 4]]maka ini harus diberi parameter sebagai a=1&b[]=2&b[]=3&b[]=4( [dan ]akan / harus URL dikodekan). Ini akan diubah kembali secara otomatis menjadi array bersarang di ujung lain (dengan asumsi di sini ujung lainnya juga PHP).

Ini akan berhasil:

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"

Ini tidak akan berhasil:

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

Ini akan memberi Anda pemberitahuan. Eksekusi kode akan berlanjut dan titik akhir Anda akan menerima parameter bsebagai string "Array":

Pemberitahuan PHP: Konversi Array ke string di ... on line ...

7ochem
sumber
4

Itu tergantung pada content-type

url-encoded atau multipart / form-data

Untuk mengirim data dengan cara standar, seperti yang dilakukan browser dengan formulir, cukup berikan array asosiatif . Seperti yang dinyatakan oleh manual PHP:

Parameter ini dapat dikirimkan sebagai string yang dikodekan url seperti 'para1 = val1 & para2 = val2 & ...' atau sebagai larik dengan nama bidang sebagai kunci dan data bidang sebagai nilai. Jika nilainya adalah larik, header Tipe Konten akan disetel ke multipart / form-data.

Pengkodean JSON

Namun, saat berkomunikasi dengan JSON API, konten harus dikodekan JSON agar API dapat memahami data POST kami.

Dalam kasus seperti itu, konten harus dienkode secara eksplisit sebagai JSON:

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

Saat berkomunikasi di JSON, kami juga biasanya menyetel acceptdan memberi content-typeheader yang sesuai:

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

untuk larik bersarang, Anda dapat menggunakan:

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

Menariknya, cara Postman melakukan POST adalah operasi GET lengkap dengan 2 opsi tambahan berikut:

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

Hanya dengan cara lain, dan itu bekerja dengan sangat baik.

Klompenrunner
sumber
-3

Jawaban ini membutuhkan waktu lama untuk saya temukan juga. Saya menemukan bahwa yang harus Anda lakukan adalah menggabungkan URL ('?' Setelah nama file dan ekstensi) dengan string kueri yang dikodekan URL. Ini bahkan tidak terlihat seperti Anda harus menyetel opsi POST cURL. Lihat contoh palsu di bawah ini:

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

Anda juga bisa menggunakan file_get_contents():

// read entire webpage file into a string
$output = file_get_contents($exampleURL . $data);
pengguna2512571
sumber
9
Sepertinya Anda melakukan GET daripada POST.
grandnasty