<?php
function http_post(string $url, array $data, array $options = []): string|false {
$defaults = [
'timeout' => 10,
'connect_timeout' => 5,
'headers' => ['Content-Type: application/x-www-form-urlencoded'],
'follow_location' => true,
'max_redirects' => 3,
'ssl_verify_peer' => true,
'ssl_verify_host' => 2,
];
$opts = array_merge($defaults, $options);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query($data), // 自動編碼
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => $opts['timeout'],
CURLOPT_CONNECTTIMEOUT => $opts['connect_timeout'],
CURLOPT_FOLLOWLOCATION => $opts['follow_location'],
CURLOPT_MAXREDIRS => $opts['max_redirects'],
CURLOPT_SSL_VERIFYPEER => $opts['ssl_verify_peer'],
CURLOPT_SSL_VERIFYHOST => $opts['ssl_verify_host'],
CURLOPT_HTTPHEADER => $opts['headers'],
]);
$response = curl_exec($ch);
$errno = curl_errno($ch);
$error = curl_error($ch);
$info = curl_getinfo($ch);
curl_close($ch);
if ($errno) {
error_log("cURL error [$errno] $error for $url");
return false;
}
if ($info['http_code'] >= 400) {
error_log("HTTP {$info['http_code']} for $url");
}
return $response;
}
// 使用
$res = http_post('https://api.example.com/notify', [
'event' => 'order_created',
'order_id' => 12345,
'amount' => 99.00,
]);
if ($res !== false) {
$result = json_decode($res, true);
// 處理結果
}
?>
| 項目 | 說明 |
|---|---|
| http_build_query | 自動處理數組編碼、巢狀結構、URL 編碼,比手動拼接安全 |
| CURLOPT_RETURNTRANSFER | 返回響應體而非直接輸出 |
| 超時設置 | 區分連接超時與總超時,防止掛死 |
| SSL 驗證 | 生產環境必須開啟,內網可關閉 |
| 錯誤處理 | 檢查 curl_errno、http_code,記錄日志 |
| JSON POST | 設置 Content-Type: application/json,CURLOPT_POSTFIELDS => json_encode($data) |
function http_post_multi(array $requests, array $options = []): array {
$mh = curl_multi_init();
$handles = [];
foreach ($requests as $i => [$url, $data]) {
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query($data),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => $options['timeout'] ?? 10,
]);
curl_multi_add_handle($mh, $ch);
$handles[$i] = $ch;
}
$running = null;
do {
curl_multi_exec($mh, $running);
curl_multi_select($mh, 0.1);
} while ($running);
$results = [];
foreach ($handles as $i => $ch) {
$results[$i] = [
'response' => curl_multi_getcontent($ch),
'info' => curl_getinfo($ch),
'error' => curl_error($ch),
];
curl_multi_remove_handle($mh, $ch);
}
curl_multi_close($mh);
return $results;
}
composer require guzzlehttp/guzzle
use GuzzleHttp\Client;
$client = new Client(['timeout' => 10]);
$response = $client->post('https://api.example.com/notify', [
'form_params' => ['event' => 'order_created', 'order_id' => 12345],
'headers' => ['X-Custom' => 'value'],
]);
$data = json_decode($response->getBody(), true);
新項目強烈建議直接用 Guzzle:PSR-18 兼容、中間件、重試、異步、測試雙工、完整類型提示。原生 cURL 僅用於無 Composer 環境或極簡腳本。