19.

PHP cURL HTTP リクエスト完全ガイド

編集
この記事の要点
  • 基本: curl_init()curl_setopt()curl_exec()curl_close()
  • 必須オプション: CURLOPT_RETURNTRANSFER=true(戻り値で取得)
  • POST 送信: CURLOPT_POST=true + CURLOPT_POSTFIELDS。JSON なら Content-Type: application/json + json_encode
  • タイムアウト指定: CURLOPT_TIMEOUT 全体 / CURLOPT_CONNECTTIMEOUT 接続
  • 新規プロジェクトでは Guzzle や Laravel Http::get() を推奨(curl は内部で使われる)

基本: GET リクエスト

<?php
$ch = curl_init('https://api.example.com/users/1');

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);  // 結果を文字列で返す(必須)
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);  // 3xx リダイレクトを追う

$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);

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

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

POST 送信(フォーム形式)

<?php
$ch = curl_init('https://api.example.com/login');

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
    'email' => 'foo@example.com',
    'password' => 'secret',
]));
// http_build_query は application/x-www-form-urlencoded 形式の文字列を作る
// 自動で Content-Type: application/x-www-form-urlencoded が付く

$body = curl_exec($ch);
curl_close($ch);

POST 送信(JSON)

<?php
$payload = ['name' => 'Taro', 'age' => 30];

$ch = curl_init('https://api.example.com/users');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_POSTFIELDS     => json_encode($payload),
    CURLOPT_HTTPHEADER     => [
        'Content-Type: application/json',
        'Accept: application/json',
        'Authorization: Bearer ' . $token,
    ],
    CURLOPT_TIMEOUT        => 10,
    CURLOPT_CONNECTTIMEOUT => 3,
]);

$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($body === false || $status >= 400) {
    throw new RuntimeException("HTTP $status");
}

$created = json_decode($body, true);

PUT / PATCH / DELETE

<?php
// PUT
$ch = curl_init('https://api.example.com/users/1');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'PUT',
    CURLOPT_POSTFIELDS     => json_encode(['name' => 'Updated']),
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
]);

// PATCH も同様
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PATCH');

// DELETE
$ch = curl_init('https://api.example.com/users/1');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'DELETE',
]);

$body = curl_exec($ch);
curl_close($ch);

主要な CURLOPT 一覧

定数意味
CURLOPT_URLリクエスト URL
CURLOPT_RETURNTRANSFERtrue で結果を返り値に(false は echo)
CURLOPT_POSTtrue で POST
CURLOPT_POSTFIELDSPOST ボディ(配列 or 文字列)
CURLOPT_CUSTOMREQUESTPUT / PATCH / DELETE 等
CURLOPT_HTTPHEADER追加ヘッダ(配列)
CURLOPT_FOLLOWLOCATION3xx リダイレクト追従
CURLOPT_MAXREDIRS追従上限
CURLOPT_TIMEOUT全体タイムアウト(秒)
CURLOPT_CONNECTTIMEOUT接続タイムアウト
CURLOPT_USERAGENTUA 文字列
CURLOPT_HEADERtrue で response ヘッダもボディに含む
CURLOPT_NOBODYtrue で HEAD リクエスト
CURLOPT_SSL_VERIFYPEERSSL 証明書検証(本番では true)
CURLOPT_COOKIEJAR受信 Cookie を保存するファイル
CURLOPT_COOKIEFILE送信時に読み込む Cookie ファイル
CURLOPT_USERPWDBasic 認証 user:pass

認証

<?php
// Basic 認証
curl_setopt($ch, CURLOPT_USERPWD, 'user:password');
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);

// Bearer Token
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Authorization: Bearer ' . $token,
]);

// API Key(独自ヘッダ)
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'X-API-Key: abcdef123456',
]);

Cookie とセッション

<?php
$cookieFile = sys_get_temp_dir() . '/session.cookie';

// ログインしてセッション Cookie を保存
$ch = curl_init('https://example.com/login');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_POSTFIELDS     => http_build_query(['user'=>'a','pass'=>'b']),
    CURLOPT_COOKIEJAR      => $cookieFile,
]);
curl_exec($ch);
curl_close($ch);

// 以降のリクエストで Cookie を送信
$ch = curl_init('https://example.com/mypage');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_COOKIEFILE     => $cookieFile,
]);
$body = curl_exec($ch);

エラーハンドリング

<?php
function httpGet(string $url): array
{
    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HEADER         => false,
        CURLOPT_TIMEOUT        => 10,
        CURLOPT_CONNECTTIMEOUT => 3,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_MAXREDIRS      => 5,
        CURLOPT_SSL_VERIFYPEER => true,
    ]);

    $body = curl_exec($ch);
    $errno = curl_errno($ch);
    $error = curl_error($ch);
    $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $totalTime = curl_getinfo($ch, CURLINFO_TOTAL_TIME);
    curl_close($ch);

    if ($body === false) {
        throw new RuntimeException("cURL($errno): $error");
    }

    return [
        'status' => $status,
        'body'   => $body,
        'time'   => $totalTime,
    ];
}

Guzzle(推奨)

新規開発では生 cURL より Guzzle を強く推奨。内部で curl を使いつつ、PSR-7 / 例外ベース / Promise / ミドルウェアを提供します:

<?php
use GuzzleHttp\Client;

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

// GET
$response = $client->get('/users/1');
$data = json_decode((string) $response->getBody(), true);

// POST JSON
$response = $client->post('/users', [
    'json' => ['name' => 'Taro', 'age' => 30],
]);

// POST form
$response = $client->post('/login', [
    'form_params' => ['email' => 'a@b', 'password' => 'x'],
]);

// マルチパート(ファイルアップロード)
$response = $client->post('/upload', [
    'multipart' => [
        ['name' => 'file', 'contents' => fopen('/tmp/a.jpg', 'r')],
        ['name' => 'tag',  'contents' => 'avatar'],
    ],
]);

Laravel HTTP クライアント

<?php
use Illuminate\Support\Facades\Http;

$response = Http::withToken($token)
    ->timeout(10)
    ->retry(3, 100)
    ->get('https://api.example.com/users/1');

if ($response->successful()) {
    $data = $response->json();
}

// POST JSON
Http::post('https://api.example.com/users', ['name' => 'Taro']);

// マルチパート
Http::attach('avatar', file_get_contents('a.jpg'), 'avatar.jpg')
    ->post('https://api.example.com/upload');

FAQ

Q: CURLOPT_SSL_VERIFYPEER = false しか動かない
A: 証明書バンドルが古いか、自己署名証明書のサーバ。本来は CURLOPT_CAINFO でルート CA を指定するのが正解。false は中間者攻撃を許すので開発のみ。

Q: 並列で複数 URL を叩きたい
A: curl_multi_init() を使うか、Guzzle の Pool / Promise を使うのが簡単です。

Q: file_get_contents で HTTP は無理?
A: allow_url_fopen=On なら可能ですが、エラー処理が貧弱なため本格用途では curl / Guzzle を使ってください。

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. 基本的なルール
  2. 変数
  3. 演算子
  4. 標準ライブラリ
  5. 外部ライブラリ
  6. 制御構文
  7. リスト(配列)
  8. タプル
  9. セット
  10. 辞書(dict)
  11. クラスとメソッド
  12. 継承の概念と必要性
  13. 継承の構文
  14. コンストラクタ
  15. cookieの値の設定と取得
  16. 例外処理
  17. 例外を文字列で出力する方法
  18. httpリクエスト(curl)をする方法
  19. Responseオブジェクトの中身の確認
  20. 変数が空かどうか判定する方法
  21. タイムゾーンの設定と現在日時の取得と文字列化
  22. シングルクォーテーションとダブルクォーテーションの違い

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