PHP HTTP Client 與 API 呼叫

在現代網頁開發中,呼叫外部 API (如 LINE Bot、金流串接、或是獲取天氣資料) 是非常常見的需求。PHP 提供幾種主要方式來發送 HTTP 請求。

使用 file_get_contents()

這是最簡單的方法,主要用於發送簡單的 GET 請求。

發送 GET 請求

<?php
// API endpoint
$url = "https://jsonplaceholder.typicode.com/posts/1";

// 讀取回應內容
$response = file_get_contents($url);

if ($response !== false) {
    $data = json_decode($response, true);
    echo "標題:" . $data['title'];
} else {
    echo "請求失敗";
}
?>

發送 POST 請求 (使用 Context)

如果要發送 POST 請求或自訂 Header,需要使用 stream_context_create()

<?php
$url = 'https://jsonplaceholder.typicode.com/posts';
$data = ['title' => 'foo', 'body' => 'bar', 'userId' => 1];

$options = [
    'http' => [
        'header'  => "Content-type: application/json\r\n",
        'method'  => 'POST',
        'content' => json_encode($data),
        'ignore_errors' => true // 即使 HTTP 狀態碼不是 200 也讀取內容
    ]
];

$context  = stream_context_create($options);
$result = file_get_contents($url, false, $context);

echo $result;
?>
file_get_contents 雖然方便,但缺乏細節控制(如 Timeout、詳細的錯誤處理),在處理複雜 API 時建議使用 cURL 或 Guzzle。

使用 cURL

cURL 是 PHP 內建最強大的 HTTP 工具,幾乎可以處理任何網路請求。

基本 cURL 步驟

  1. curl_init(): 初始化
  2. curl_setopt(): 設定選項 (URL, Header, Method 等)
  3. curl_exec(): 執行請求
  4. curl_close(): 關閉連線

GET 請求範例

<?php
$ch = curl_init();

// 設定 URL
curl_setopt($ch, CURLOPT_URL, "https://api.example.com/data");
// 要求回傳內容為字串,而不是直接輸出
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// 設定超時時間(秒)
curl_setopt($ch, CURLOPT_TIMEOUT, 10);

$response = curl_exec($ch);

if (curl_errno($ch)) {
    echo '錯誤:' . curl_error($ch);
} else {
    $data = json_decode($response, true);
    print_r($data);
}

curl_close($ch);
?>

POST 請求範例 (JSON)

<?php
$url = "https://api.example.com/user";
$payload = json_encode(['name' => 'John', 'email' => 'john@example.com']);

$ch = curl_init($url);

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'Content-Length: ' . strlen($payload),
    'Authorization: Bearer YOUR_TOKEN'
]);

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

if ($httpCode === 201) {
    echo "建立成功";
} else {
    echo "失敗,狀態碼:" . $httpCode;
}

curl_close($ch);
?>

使用 Guzzle (推薦)

在實際專案中,開發者通常會使用 Guzzle,它是 PHP 界最流行的 HTTP 客戶端套件,寫法更現代化且易於測試。

安裝 Guzzle

透過 Composer 安裝:

composer require guzzlehttp/guzzle

使用範例

<?php
require 'vendor/autoload.php';

use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;

$client = new Client([
    'base_uri' => 'https://api.example.com',
    'timeout'  => 2.0,
]);

try {
    // 發送 GET 請求
    $response = $client->request('GET', '/posts/1');

    echo "狀態碼:" . $response->getStatusCode() . "\n";
    $body = $response->getBody();
    $data = json_decode($body, true);

    // 發送 POST 請求
    $response = $client->request('POST', '/posts', [
        'json' => ['title' => 'Hello Guzzle']
    ]);

} catch (RequestException $e) {
    echo "發生錯誤:" . $e->getMessage();
}
?>

總結:該選擇哪一個?

  • file_get_contents:只需快速獲取簡單的遠端 HTML 或 JSON,且不考慮效能與安全性時。
  • cURL:不想增加第三方套件依賴,或是需要極致細節控制時。
  • Guzzle:正規開發專案的首選,代碼簡潔、功能強大且易於維護。