0

Series PHP cURL Extension | Bài 2: Chinh phục POST Request – Gửi JSON, Form Data và Upload File

Chào anh em, ở Bài 1, chúng ta đã nắm được "vòng đời 4 bước" của một cURL request và cách gọi GET request để lấy dữ liệu. Nhưng đời không chỉ có lấy (GET), làm backend thì việc đẩy dữ liệu sang một hệ thống khác (POST/PUT) như đẩy log, gọi API thanh toán, hay submit data lên một microservice là chuyện xảy ra hàng ngày.

Trong bài viết hôm nay, chúng ta sẽ "giải phẫu" POST request trong cURL. Việc gửi dữ liệu tưởng chừng đơn giản nhưng lại là chỗ anh em dễ giẫm mìn nhất, đặc biệt là khi lúng túng giữa các định dạng dữ liệu: JSON, Form Data và Multipart (để upload file). Bắt đầu thôi!

1. Bản chất của POST Request trong cURL

Khi chuyển từ GET sang POST, bản chất vòng đời 4 bước không đổi. Điều duy nhất thay đổi là ở Bước 2 (Thiết lập Options). Chúng ta cần khai báo hai thông số cốt lõi:

  1. Báo cho cURL biết đây là POST request: Dùng CURLOPT_POST hoặc CURLOPT_CUSTOMREQUEST.
  2. Gắn dữ liệu vào body của request: Dùng CURLOPT_POSTFIELDS.

Lưu ý tử huyệt: Việc API đích có hiểu được dữ liệu bạn gửi hay không phụ thuộc 100% vào Header Content-Type mà bạn cấu hình.

2. Kịch bản 1: Gửi dữ liệu chuẩn RESTful (JSON Payload)

Hiện nay, 90% các API hiện đại đều giao tiếp bằng JSON. Đây là kịch bản bạn sẽ gặp nhiều nhất.

<?php

$url = 'https://jsonplaceholder.typicode.com/posts';

// Dữ liệu mảng PHP nguyên thủy
$payload = [
    'title' => 'Bài 2 cURL',
    'body'  => 'Hướng dẫn POST request',
    'userId' => 1
];

$ch = curl_init($url);

// Cấu hình cURL
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// Bật cờ POST
curl_setopt($ch, CURLOPT_POST, true);
// Encode mảng PHP thành chuỗi JSON và gắn vào body
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));

// QUAN TRỌNG: Báo cho server biết ta đang gửi JSON
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'Accept: application/json'
]);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

if (curl_errno($ch)) {
    echo "Lỗi: " . curl_error($ch);
} else {
    echo "HTTP Status Code: $httpCode \n";
    echo "Phản hồi từ server: $response";
}

curl_close($ch);

?>

3. Kịch bản 2: Gửi dữ liệu Form thông thường (URL-encoded)

Khi bạn tích hợp các cổng thanh toán cũ hoặc các API yêu cầu dữ liệu y hệt như việc submit một thẻ <form> HTML truyền thống, định dạng cần dùng là application/x-www-form-urlencoded.

Với cURL, bạn có thể truyền một chuỗi query string (vd: name=hieu&role=admin) hoặc truyền thẳng một mảng (array) PHP vào CURLOPT_POSTFIELDS. Trình biên dịch sẽ tự động encode nó.

<?php

$url = 'https://httpbin.org/post';

$formData = [
    'username' => 'hieu_backend',
    'password' => 'secret123'
];

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);

// Truyền thẳng mảng vào. cURL sẽ tự động set Header Content-Type thành application/x-www-form-urlencoded
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($formData)); 

$response = curl_exec($ch);
curl_close($ch);

echo $response;
?>

Tip: Luôn dùng hàm http_build_query() của PHP khi truyền array vào CURLOPT_POSTFIELDS cho form data để đảm bảo các ký tự đặc biệt (khoảng trắng, dấu +, &...) được mã hóa an toàn.

4. Kịch bản 3: Upload File (Multipart Form Data)

Để gửi file (hình ảnh, tài liệu) qua API, bạn bắt buộc phải dùng định dạng multipart/form-data. Từ PHP 5.5 trở đi, chúng ta sử dụng class CURLFile để xử lý việc này một cách chuẩn xác và bảo mật.

<?php

$url = 'https://httpbin.org/post';

// Đường dẫn tuyệt đối tới file trên server của bạn
$filePath = realpath(__DIR__ . '/test-image.jpg'); 

// Tạo một đối tượng CURLFile
// Tham số 1: Đường dẫn file
// Tham số 2: Mime type (vd: image/jpeg, application/pdf...)
// Tham số 3: Tên file khi gửi lên
$cFile = new CURLFile($filePath, 'image/jpeg', 'uploaded_image.jpg');

$postData = [
    'description' => 'Đây là ảnh test upload qua cURL',
    'file_upload' => $cFile // Gắn đối tượng CURLFile vào key tương ứng
];

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
// Truyền mảng chứa CURLFile vào. cURL sẽ tự động set Content-Type thành multipart/form-data
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); 

$response = curl_exec($ch);
curl_close($ch);

echo $response;
?>

Tổng kết Bài 2

Gửi dữ liệu qua cURL không khó, bí quyết cốt lõi nằm ở việc ghép nối đúng định dạng dữ liệu (Payload) với Header (Content-Type) tương ứng. Khớp đúng chìa với ổ thì API nào cũng có thể gọi thành công.

Ở Bài 3, chúng ta sẽ đối mặt với các bài toán khó nhằn hơn trong thực tế: Xử lý Authentication (Bearer Token, Basic Auth), vượt rào SSL Certificate và cách gỡ rối (Debug) khi cURL không chịu chạy. Hẹn anh em ở bài sau!


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí