21.

PHPでAPIを呼び出す方法|cURL・file_get_contents・Guzzle

編集
この記事の要点
  • PHP から HTTP API を呼ぶ主な方法は cURL(curl_*) / file_get_contents + ストリームコンテキスト / Guzzle の 3 系統
  • 最も柔軟で実戦的なのは cURL。タイムアウト・ヘッダ・SSL 検証など細かい制御ができる
  • GET / POST / PUT / DELETE は CURLOPT_CUSTOMREQUESTCURLOPT_POSTFIELDS で指定
  • JSON API は リクエストで json_encode、レスポンスで json_decode がセット
  • SSL 検証無効化(VERIFYPEER=false)は本番禁止。証明書バンドルを正しく指定する

PHP から API を呼ぶ 3 つの方法

方式長所短所
cURL(curl_*柔軟、高速、ヘッダや SSL を細かく制御コードがやや冗長
file_get_contents + コンテキスト1 行で書けるPOST / ヘッダがやや書きにくい、allow_url_fopen 必要
Guzzle(HTTP クライアントライブラリ)API がモダン、非同期 / リトライ / ミドルウェア対応Composer 必須

方法 1: cURL で GET

$apiUrl = 'https://api.example.com/users/1';

$curl = curl_init();
curl_setopt_array($curl, [
    CURLOPT_URL            => $apiUrl,
    CURLOPT_CUSTOMREQUEST  => 'GET',
    CURLOPT_RETURNTRANSFER => true,   // 結果を文字列で返す
    CURLOPT_TIMEOUT        => 10,     // タイムアウト 10 秒
    CURLOPT_CONNECTTIMEOUT => 5,
    CURLOPT_FOLLOWLOCATION => true,   // リダイレクト追従
    CURLOPT_HTTPHEADER     => [
        'Accept: application/json',
        'Authorization: Bearer ' . $token,
    ],
]);

$response = curl_exec($curl);
$status   = curl_getinfo($curl, CURLINFO_HTTP_CODE);
$err      = curl_error($curl);
curl_close($curl);

if ($response === false) {
    throw new RuntimeException('cURL error: ' . $err);
}
if ($status >= 400) {
    throw new RuntimeException("HTTP $status: $response");
}

$data = json_decode($response, true);
print_r($data);

方法 2: cURL で POST(JSON ボディ)

$apiUrl  = 'https://api.example.com/users';
$payload = json_encode([
    'name'  => '山田太郎',
    'email' => 'taro@example.com',
], JSON_UNESCAPED_UNICODE);

$curl = curl_init();
curl_setopt_array($curl, [
    CURLOPT_URL            => $apiUrl,
    CURLOPT_CUSTOMREQUEST  => 'POST',
    CURLOPT_POSTFIELDS     => $payload,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => [
        'Content-Type: application/json',
        'Accept: application/json',
        'Content-Length: ' . strlen($payload),
    ],
    CURLOPT_TIMEOUT        => 10,
]);

$response = curl_exec($curl);
$status   = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);

方法 3: cURL で PUT / DELETE

// PUT
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));

// DELETE
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'DELETE');

方法 4: file_get_contents で簡易呼び出し

// GET
$response = file_get_contents('https://api.example.com/items');
$data = json_decode($response, true);

// POST(ストリームコンテキスト)
$options = [
    'http' => [
        'method'  => 'POST',
        'header'  => "Content-Type: application/json\r\n" .
                     "Accept: application/json\r\n",
        'content' => json_encode(['name' => 'apple']),
        'timeout' => 10,
        'ignore_errors' => true,  // 4xx / 5xx でも本文を取得
    ],
];
$ctx = stream_context_create($options);
$response = file_get_contents('https://api.example.com/items', false, $ctx);

// レスポンスヘッダは $http_response_header に自動で入る
print_r($http_response_header);

注意: file_get_contents での URL 取得は allow_url_fopen=On が必要です。本番サーバではセキュリティ上オフにする運用もあるため、その場合は cURL を使います。

方法 5: Guzzle(推奨・モダン)

composer require guzzlehttp/guzzle
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;

$client = new Client([
    'base_uri' => 'https://api.example.com/',
    'timeout'  => 10,
    'headers'  => [
        'Authorization' => 'Bearer ' . $token,
        'Accept'        => 'application/json',
    ],
]);

try {
    // GET
    $res  = $client->get('users/1');
    $user = json_decode($res->getBody(), true);

    // POST (json オプションが自動エンコード)
    $res = $client->post('users', [
        'json' => ['name' => '山田', 'email' => 'taro@example.com'],
    ]);

    // クエリパラメータ
    $res = $client->get('users', [
        'query' => ['page' => 2, 'limit' => 20],
    ]);
} catch (RequestException $e) {
    error_log('API error: ' . $e->getMessage());
    if ($e->hasResponse()) {
        error_log('Body: ' . $e->getResponse()->getBody());
    }
}

クエリパラメータの組み立て

$params = ['q' => 'PHP cURL', 'lang' => 'ja', 'page' => 2];
$url    = 'https://api.example.com/search?' . http_build_query($params);
// → https://api.example.com/search?q=PHP+cURL&lang=ja&page=2

SSL 証明書の扱い(重要)

古いサンプルでよくある CURLOPT_SSL_VERIFYPEER = false本番投入禁止です。中間者攻撃(MITM)に対し丸腰になります。社内自己署名 CA を使う場合は明示的に CA バンドルを指定します。

// 正しい指定(公的 CA バンドル)
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($curl, CURLOPT_CAINFO, '/etc/ssl/certs/ca-certificates.crt');

// 自己署名 CA を使うケースのみ
curl_setopt($curl, CURLOPT_CAINFO, '/path/to/internal-ca.pem');

タイムアウトとリトライ

オプション意味推奨値
CURLOPT_CONNECTTIMEOUT接続確立までの上限3〜5 秒
CURLOPT_TIMEOUT処理全体の上限10〜30 秒

5xx / ネットワークエラー時のリトライは指数バックオフで 2〜3 回が目安。POST 系の非冪等なリクエストはリトライしない(同じ処理が二重実行される)。

ステータスコード別の処理

switch (true) {
    case $status >= 200 && $status < 300:
        // 成功
        break;
    case $status === 401 || $status === 403:
        throw new AuthException('認証エラー');
    case $status === 404:
        throw new NotFoundException('リソース無し');
    case $status === 429:
        // レート制限 → Retry-After に従って待機
        break;
    case $status >= 500:
        throw new ServerException('サーバ側エラー');
    default:
        throw new ApiException("Unexpected $status");
}

セキュリティのチェックリスト

  • API キー / トークンは環境変数.env)に置き、コードに直書きしない
  • SSL_VERIFYPEERtrueのまま
  • レスポンスをそのままユーザーに出力する場合はエスケープ必須
  • 外部 URL を動的に組み立てる場合は SSRF 対策(プライベート IP への接続禁止など)
  • ログにトークンを出さない

関連

  • API
  • REST
  • cURL / curl_init / curl_exec
  • json_encode / json_decode
  • Guzzle HTTP クライアント
編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. インストール方法
  2. 文法
  3. Composerのインストール
  4. 内部関数
  5. フレームワーク
  6. エラー一覧
  7. 改行出力
  8. printとechoの違い
  9. シングルクォートとダブルクォートの違い
  10. returnとyieldの違い
  11. var_dumpをログ出力
  12. CSV読み込み
  13. 待機・処理の遅延
  14. ログファイルにエラーを出力する方法
  15. エラーログ出力関数
  16. URLパラメータの配列化
  17. empty, is_null. issetの判定比較表
  18. httpステータスコードの付与
  19. バージョンの確認
  20. php.ini
  21. APIを呼び出す方法
  22. 外部ファイルを呼び出す方法
  23. カンマ区切りの文字列を配列に変換
  24. 配列からランダムに値を取り出す方法
  25. Webスクレイピング

最近更新/作成されたページ