cuộn tròn định dạng POST cho CURLOPT_POSTFIELDS


99

Khi tôi sử dụng curlqua POSTvà đặt CURLOPT_POSTFIELDtôi có phải urlencodehoặc bất kỳ định dạng đặc biệt nào không?

ví dụ: Nếu tôi muốn đăng 2 trường, đầu tiên và cuối cùng:

first=John&last=Smith

mã / định dạng chính xác nên được sử dụng với curl là gì?

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

Câu trả lời:


100

Trong trường hợp bạn đang gửi một chuỗi, hãy urlencode () nó. Nếu không, nếu mảng, nó phải là key => giá trị được ghép nối và Content-typetiêu đề được tự động đặt thành multipart/form-data.

Ngoài ra, bạn không phải tạo các hàm bổ sung để xây dựng truy vấn cho các mảng của mình, bạn đã có:

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

13
Bạn chỉ có thể sử dụng http_build_query($data)&là dấu phân tách mặc định.
nullability

6
Tất nhiên bạn có thể bỏ qua chúng. Đây là để minh họa hai đối số khác mà bạn có thể (hoặc có thể không) thay đổi (ví dụ: dấu phân tách mặc định) cho phù hợp với nhu cầu cụ thể của bạn.
kodeart

62

CHỈNH SỬA : Từ php5 trở lên, http_build_querykhuyến nghị sử dụng :

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

Ví dụ đơn giản từ sách hướng dẫn:

<?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
*/

?>

trước php5:

Từ sách hướng dẫn :

CURLOPT_POSTFIELDS

Toàn bộ dữ liệu để đăng trong thao tác HTTP "POST". Để đăng tệp, hãy thêm trước tên tệp bằng @ và sử dụng đường dẫn đầy đủ. Loại tệp có thể được chỉ định rõ ràng bằng cách theo sau tên tệp với kiểu ở định dạng '; type = mimetype'. Tham số này có thể được chuyển dưới dạng chuỗi được mã hóa urê như 'para1 = val1 & para2 = val2 & ...' hoặc dưới dạng một mảng với tên trường là khóa và dữ liệu trường là giá trị. Nếu giá trị là một mảng, tiêu đề Loại-Nội dung sẽ được đặt thành nhiều phần / biểu mẫu-dữ liệu. Kể từ PHP 5.2.0, các tệp được chuyển đến tùy chọn này với tiền tố @ phải ở dạng mảng để hoạt động.

Vì vậy, một cái gì đó như thế này sẽ hoạt động hoàn hảo (với các tham số được truyền trong một mảng kết hợp):

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

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

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

11
Tại sao bạn sẽ truyền một chuỗi nếu bạn có thể truyền một mảng ...?
ThiefMaster

1
Tôi nghĩ rằng $ key nên được mã hóa cũng vậy, chỉ trong trường hợp bạn có nó như "tên & họ" vv Đặc biệt, nếu dữ liệu được đưa ra bởi người dùng cuối
Marius Balčytis

2
@barius, tôi đồng ý với bạn. Và tôi nghĩ rằng http_build_query () thực sự tốt hơn hàm được định nghĩa ở trên.
skyfree vào

1
@skyfree Tôi đồng ý! Đó là chức năng được bổ sung trong php5 dù đó vẫn còn xa tiêu chuẩn trong năm 2011.
Czechnology

1
tại sao cần có http_build_query khi bạn chỉ có thể truyền mảng?
Offenso

39

Không vượt qua một chuỗi nào cả!

Bạn có thể chuyển một mảng và để php / curl thực hiện công việc mã hóa bẩn thỉu, v.v.


16
truyền một mảng sẽ là một Kiểu nội dung khác với một chuỗi, vì vậy có lý do chính đáng để làm như vậy. Tôi đã mất một thời gian để tìm ra điều đó.
Thomas Vander Stichele

Tôi không có ý tưởng tại sao, nhưng tôi thấy rằng trên chiến thắng dev pc của tôi đi qua một mảng mất khoảng một giây lâu hơn (1.029s sử dụng 0.016s mảng so với sử dụng http_build_query()trên mảng giống nhau)
kratenko

2
Các mảng lồng nhau sẽ không hoạt động. cURL sẽ cố gắng để chuyển đổi chúng sang chuỗi và một PHP mảng để chuyển đổi chuỗi thông báo sẽ đi theo
7ochem


4

Đối với CURLOPT_POSTFIELDS, các tham số có thể được truyền dưới dạng một chuỗi được mã hóa urê như para1=val1&para2=val2&..hoặc dưới dạng một mảng với tên trường là khóa và dữ liệu trường là giá trị

Hãy thử định dạng sau:

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

2
Xin chào Shraddha, json_encode()sẽ cung cấp cho bạn một cái gì đó thực sự khác biệt của một chuỗi tham số hợp lệ như first=John&last=Smith. json_encode()sẽ xuất: {"first":"John","last":"Smith"}sau đó sẽ trở thành phần thân thô của yêu cầu POST của bạn.
7ochem

1
Để thêm vào nhận xét của @ 7ochem: Trừ khi người nhận đang mong đợi một tham số duy nhất chứa chuỗi mã hóa json , thay vì json_encode(...)làm như vậy http_build_query(...). Điều này sẽ tạo ra "chuỗi được mã hóa url" dự kiến ​​chứa các tham số được phân tách bằng "&".
ToolmakerSteve

4

Một khác biệt lớn khác chưa được đề cập ở đây là CURLOPT_POSTFIELDSkhông thể xử lý các mảng lồng nhau.

Nếu chúng ta lấy mảng lồng nhau ['a' => 1, 'b' => [2, 3, 4]]thì mảng này phải được tham số hóa là a=1&b[]=2&b[]=3&b[]=4( URL đang []sẽ được / phải được mã hóa). Điều này sẽ được chuyển đổi tự động trở lại thành một mảng lồng nhau ở đầu kia (giả sử ở đây đầu kia cũng là PHP).

Điều này sẽ hoạt động:

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"

Điều này sẽ không hoạt động:

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

Điều này sẽ cung cấp cho bạn một thông báo. Quá trình thực thi mã sẽ tiếp tục và điểm cuối của bạn sẽ nhận được tham số bdưới dạng chuỗi "Array":

Thông báo PHP: Chuyển đổi mảng thành chuỗi trong ... trên dòng ...


4

Nó phụ thuộc vào content-type

được mã hóa url hoặc đa phần / dữ liệu biểu mẫu

Để gửi dữ liệu theo cách chuẩn, như một trình duyệt làm với một biểu mẫu, chỉ cần chuyển một mảng liên kết . Như đã nêu trong sách hướng dẫn của PHP:

Tham số này có thể được chuyển dưới dạng chuỗi được mã hóa urê như 'para1 = val1 & para2 = val2 & ...' hoặc dưới dạng một mảng với tên trường là khóa và dữ liệu trường là giá trị. Nếu giá trị là một mảng, tiêu đề Loại-Nội dung sẽ được đặt thành nhiều phần / biểu mẫu-dữ liệu.

Mã hóa JSON

Tuy nhiên, khi giao tiếp với các API JSON, nội dung phải được mã hóa JSON để API hiểu được dữ liệu POST của chúng tôi.

Trong những trường hợp như vậy, nội dung phải được mã hóa rõ ràng dưới dạng JSON:

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

Khi giao tiếp bằng JSON, chúng tôi cũng thường đặt acceptcontent-typetiêu đề cho phù hợp:

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

2

đối với các mảng lồng nhau, bạn có thể sử dụng:

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

0

Điều thú vị là cách Postman thực hiện POST là hoạt động GET hoàn chỉnh với 2 tùy chọn bổ sung sau:

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

Chỉ là một cách khác, và nó hoạt động rất tốt.


-3

Câu trả lời này cũng khiến tôi tìm mãi không ra. Tôi phát hiện ra rằng tất cả những gì bạn phải làm là nối URL ('?' Sau tên tệp và phần mở rộng) với chuỗi truy vấn được mã hóa URL. Nó thậm chí không giống như bạn phải đặt các tùy chọn ĐĂNG cURL. Xem ví dụ giả bên dưới:

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

Bạn cũng có thể sử dụng file_get_contents():

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

9
Có vẻ như bạn đang thực hiện GET hơn là POST.
grandectors
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.