抓取遠端資源是後端開發常見需求。早期開發者偏愛 file_get_contents() 簡潔易用,但實戰中頻遭超時失效、無法自訂 Header、錯誤處理貧弱等痛點。本文實測對比兩者效能與穩定性,並提供生產級 curl 封裝函數。
$ctx = stream_context_create([
'http' => ['method' => 'GET', 'timeout' => 5] // 官方文件範例
]);
file_get_contents('https://target.com', false, $ctx);
實測發現:timeout 參數在某些 PHP 版本、特定網路環境下完全不生效,導致進程長時間阻塞、CPU 飆升、連線池耗盡。
| 方式 | 耗時(秒) |
|---|---|
| file_get_contents | 2.21 ~ 3.31 |
| curl | 0.64 ~ 0.82 |
curl 平均快 3~4 倍,且穩定性顯著更高。
function curl_get_contents(string $url, int $timeout = 5): ?string
{
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => $timeout, // 總超時(秒)
CURLOPT_CONNECTTIMEOUT => 3, // 連線階段超時
CURLOPT_USERAGENT => 'Mozilla/5.0 (compatible; MyBot/1.0)',
CURLOPT_REFERER => 'https://www.example.com/',
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 5,
CURLOPT_SSL_VERIFYPEER => true, // 生產環境請保持驗證
CURLOPT_SSL_VERIFYHOST => 2,
]);
$data = curl_exec($ch);
$errno = curl_errno($ch);
$error = curl_error($ch);
curl_close($ch);
if ($errno) {
error_log("cURL error [$errno]: $error for $url");
return null;
}
return $data;
}
CURLOPT_TIMEOUT / CURLOPT_CONNECTTIMEOUT 經實測極其可靠。curl_errno() / curl_error() 便於監控告警。結論:除非極簡單的本地檔案讀取,所有遠端 HTTP 請求首選 curl。若環境未安裝 curl 擴展,請優先解決擴展缺失,而非妥協使用 stream context。