この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:4
ページ更新者:T
更新日時:2026-06-11 07:07:02

タイトル: httpリクエスト(curl)をする方法
SEOタイトル: 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 リクエスト

= 400) {
    throw new RuntimeException("HTTP $status: $body");
}

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

POST 送信(フォーム形式)

 '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)

 '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

 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

認証

Cookie とセッション

 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);

エラーハンドリング

 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 / ミドルウェアを提供します:

 '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 クライアント

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 を使ってください。