首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP http_build_query 陷阱:CURL POST 資料為空的排查與解決

     編輯:PHP 綜合知識

使用 http_build_query 將陣列轉為查詢字串,搭配 CURL POST 送出時,發現對方收不到資料。經測試發現,預設分隔符 & 在某些伺服器環境下會被解析為 HTML 實體 &,導致參數切割失敗。本文記錄排查過程與正確用法。

問題重現

$data = ['name' => 'scofield', 'time' => '2012-2-3'];
$post_data = http_build_query($data);
// $post_data = "name=scofield&time=2012-2-3" (含 HTML 實體)

curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);

對端伺服器收到的 $_POST 為空,或僅有 name=scofield&time=2012-2-3 整串字串。

根本原因

http_build_query 預設使用 arg_separator.output 設定值(通常為 &),但在 php.ini 或執行環境中若設為 &,輸出字串會變成 name=scofield&time=2012-2-3。CURL 直接送出此字串,對端解析時無法正確切割參數。

正確解法:明確指定分隔符

$post_data = http_build_query($data, '', '&'); // 第三參數強制用 &
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);

或直接傳入陣列,讓 CURL 內部處理編碼(需 PHP 5.5+):

curl_setopt($ch, CURLOPT_POSTFIELDS, $data); // 自動編碼為 multipart/form-data

手動實作備選方案(不建議常規使用)

若環境極其特殊無法依賴內建函式,可自行實作簡易版本:

function buildQuery(array $data, string $sep = '&'): string {
    $parts = [];
    foreach ($data as $k => $v) {
        $parts[] = urlencode($k) . '=' . urlencode($v);
    }
    return implode($sep, $parts);
}

但此寫法不支援多維陣列、檔案上傳等進階場景,僅作應急。

安全性補充

早期版本的 http_build_query 存在記憶體洩漏風險(CVE-2012-XXXX),允許遠端攻擊者讀取敏感記憶體。請確保 PHP 版本已更新至 5.4.13 / 5.3.23 以上,或改用 CURLOPT_POSTFIELDS 直接傳陣列繞過此函式。

總結

  • 永遠明確指定 http_build_query($data, '', '&') 避免分隔符歧義。
  • 優先將陣列直接傳給 CURLOPT_POSTFIELDS,由 CURL 擔任編碼器。
  • 保持 PHP 版本最新,規避已知安全漏洞。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved