在 PHP 開發中,向遠程 API 推送 XML 數據是常見需求。本文將深入解析兩種主流實現方案:cURL 庫(推薦)與 fsockopen 底層 Socket,並提供可直接落地的代碼範例。
cURL 是 PHP 中處理 HTTP 請求的標準利器,支持 HTTPS、超時控制、錯誤捕獲等企業級特性。
<?php
$xml_data = '<xml><order_id>20231001</order_id><amount>99.00</amount></xml>';
$url = 'https://api.example.com/notify';
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $xml_data,
CURLOPT_HTTPHEADER => ['Content-Type: text/xml; charset=utf-8'],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10, // 秒級超時
CURLOPT_SSL_VERIFYPEER => true, // 生產環境務必驗證憑證
]);
$response = curl_exec($ch);
if ($response === false) {
throw new RuntimeException('cURL 錯誤: ' . curl_error($ch), curl_errno($ch));
}
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// 業務邏輯處理 $response ...
?>
關鍵點提示:
CURLOPT_HTTPHEADER 明確聲明 Content-Type: text/xml,避免服務端解析失敗。CURLOPT_SSL_VERIFYPEER = true,並配置 CA 憑證路徑。curl_getinfo() 獲取 HTTP 狀態碼,配合業務碼雙重校驗。當環境禁用 cURL 或需極致控制協議細節時,原生 Socket 是備選方案。需手動拼裝 HTTP 協議報文。
<?php
function postXmlBySocket(string $host, string $path, string $xml, int $port = 80, int $timeout = 10): string
{
$fp = fsockopen($host, $port, $errno, $errstr, $timeout);
if (!$fp) {
throw new RuntimeException("Socket 連接失敗 [$errno]: $errstr");
}
$contentLength = strlen($xml);
$request = "POST $path HTTP/1.1\r\n"
. "Host: $host\r\n"
. "Content-Type: text/xml; charset=utf-8\r\n"
. "Content-Length: $contentLength\r\n"
. "Connection: close\r\n\r\n"
. $xml;
fwrite($fp, $request);
stream_set_timeout($fp, $timeout);
$response = '';
while (!feof($fp)) {
$response .= fgets($fp, 8192);
}
fclose($fp);
// 簡易分離 Header 與 Body(生產建議用成熟解析器)
list($header, $body) = explode("\r\n\r\n", $response, 2) + ['', ''];
return $body;
}
// 使用示例
try {
$xml = '<data><key>value</key></data>';
$result = postXmlBySocket('api.example.com', '/endpoint', $xml, 443); // HTTPS 需配合 stream_context_create
echo $result;
} catch (Throwable $e) {
error_log($e->getMessage());
}
?>
避坑指南:
stream_socket_client('ssl://host:443') 或配合 stream_context_create(['ssl' => [...])。Content-Length 必須精確,否則服務端會讀取阻塞。guzzlehttp/psr7 等庫,避免手寫正則出錯。| 維度 | cURL | fsockopen |
|---|---|---|
| 易用性 | ⭐⭐⭐⭐⭐ | ⭐⭐ |
| HTTPS 支持 | 原生完美支持 | 需手動配置 SSL Context |
| 錯誤處理 | 豐富錯誤碼/信息 | 僅基礎 errno/errstr |
| 性能 | 極高(C 底層) | 略低(PHP 用戶態) |
| 適用場景 | 99% 業務首選 | 教學、極簡環境、協議調試 |
建議: 現代 PHP 專案首選 GuzzleHttp 或 Symfony HttpClient 等 PSR-18 兼容客戶端,封裝了重試、中介軟體、異步等高級特性,代碼更優雅健壯。