タイトル: httpリクエスト(curl)をする方法
SEOタイトル: PHP cURL HTTP リクエスト完全ガイド
| この記事の要点 |
|
基本: 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_RETURNTRANSFER | true で結果を返り値に(false は echo) |
CURLOPT_POST | true で POST |
CURLOPT_POSTFIELDS | POST ボディ(配列 or 文字列) |
CURLOPT_CUSTOMREQUEST | PUT / PATCH / DELETE 等 |
CURLOPT_HTTPHEADER | 追加ヘッダ(配列) |
CURLOPT_FOLLOWLOCATION | 3xx リダイレクト追従 |
CURLOPT_MAXREDIRS | 追従上限 |
CURLOPT_TIMEOUT | 全体タイムアウト(秒) |
CURLOPT_CONNECTTIMEOUT | 接続タイムアウト |
CURLOPT_USERAGENT | UA 文字列 |
CURLOPT_HEADER | true で response ヘッダもボディに含む |
CURLOPT_NOBODY | true で HEAD リクエスト |
CURLOPT_SSL_VERIFYPEER | SSL 証明書検証(本番では true) |
CURLOPT_COOKIEJAR | 受信 Cookie を保存するファイル |
CURLOPT_COOKIEFILE | 送信時に読み込む Cookie ファイル |
CURLOPT_USERPWD | Basic 認証 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 を使ってください。