PHP cURL の使い方
PHP で外部 API と通信する際、最もよく使われる手段のひとつである cURL について、curl_init による初期化から、curl_setopt でのオプション指定、curl_exec の実行、エラー処理、JSONレスポンスの扱いまで、基本的な流れを解説します。また、具体的なリクエストのサンプルも掲載しています。
更新日:2025年05月11日
作成日:2025年05月10日
cURL の基本的な使い方
PHP の cURL(Client URL Library)は、HTTP リクエストを行うための拡張機能です。
cURL を使うと、他のサーバーに HTTP リクエストを送ってデータを取得・送信できます。
cURL の基本的な使い方は次の「4ステップ」です。
- curl_init() により cURL セッションを初期化
- curl_setopt() により転送時のオプションを設定
- curl_exec() により転送を実行
- curl_close() によりセッションを終了
// 1. セッションを初期化
$ch = curl_init(); // 戻り値 $ch は cURL ハンドル(セッションを管理するためのオブジェクト)
// 2. オプションを設定
curl_setopt($ch, CURLOPT_URL, "https://example.com"); // リクエスト先を指定
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 結果を文字列で取得(出力しない)
// 3. 実行して結果を取得
$response = curl_exec($ch);
// 4. セッションを終了
curl_close($ch);
上記を実行するとリクエスト先に指定した URL のソース(HTML)が $response に格納されます。
PHP マニュアル:基本的な curl の使用法
以下は cURL で使用する各関数の詳細です。
curl_init
curl_init() は新規セッションを初期化し、cURL ハンドル(セッションハンドル)を返します。
cURL ハンドルは、PHP 内部で cURL セッションを管理するためのオブジェクト(CurlHandle クラスのインスタンス)で、以降の curl_setopt() や curl_exec() などでこのセッションを操作するために使います。
以下が書式です。
curl_init(?string $url = null): CurlHandle|false
パラメータ | 説明 |
---|---|
$url | url を指定した場合、オプション CURLOPT_URL がそのパラメータの値に設定されます。 |
書式の ?string $url = null における ? の意味は、その引数が null を許容する nullable 型であることを示していて、?string は、この引数は「文字列 または null」のどちらかを受け入れることを意味します。
戻り値
成功した場合に cURL ハンドル(セッションハンドル)、エラー時に false を返します。
// セッションを初期化(戻り値の cURL ハンドルを変数 $ch に代入)
$ch = curl_init();
var_dump($ch); // object(CurlHandle)#1 (0) { }
(補足)PHP 8.0 以降
PHP 8.0 から curl_init() の戻り値はリソース型から CurlHandle オブジェクトに変更されています。但し、従来どおり $ch(セッションハンドル)として扱えます。また、コードの書き方も基本的に同じです。
curl_init() に URL を指定しない?
一般的には、curl_init() に URL を直接渡すのではなく、以下のような理由により後から curl_setopt() や curl_setopt_array() で CURLOPT_URL を設定することが多いです。
- 柔軟性が高くなる
- curl_init() の引数で URL を渡してしまうと、URL の設定が「固定」になる。
- curl_setopt() を使えば、状況に応じて後から URL を決定・変更できるため、より柔軟。
- リクエストの構成を分かりやすく整理できる
- curl_setopt() を使ってまとめてオプションを設定する方がコードの見通しが良く、保守性も高い。
- 複数リクエストを 1 つのセッションで使いまわせる(但し注意点あり)
- 同じ cURL ハンドルを使って複数のリクエストを送ることも理論上は可能です(それにより初期化コストを多少削減できるが、接続が再利用されるとは限らない)。
- 但し、セッション情報(Cookie など)が引き継がれる可能性があるため、別セッションとして完全に独立させたい場合は curl_init() を分けたほうが安全です。もし、複数リクエストを効率よく扱いたい場合は cURL のマルチハンドル(curl_multi_* 系関数)を利用できます。
- 他のオプションとの兼ね合いを調整しやすい
- 例えばヘッダーや POST データを送る場合など、URL を決めるタイミングとオプションを決めるタイミングを柔軟に管理できます。
curl_setopt()
curl_setopt() を使って転送用のオプションを設定します。以下が書式です。
curl_setopt(CurlHandle $handle, int $option, mixed $value): bool
パラメータ | 説明 |
---|---|
$handle | curl_init() が返す cURL ハンドル |
$option | CURLOPT_URL や CURLOPT_RETURNTRANSFER などのオプション名(定数) |
$value | $option に設定する値。 |
以下はよく使うオプションです。
オプション名 | 内容 | 値の型 | デフォルト |
---|---|---|---|
CURLOPT_URL | リクエストする URL を指定 | string | なし |
CURLOPT_RETURNTRANSFER | true にすると curl_exec の結果を文字列として返す | bool | false |
CURLOPT_POST | POST メソッドを使用する | bool | false |
CURLOPT_POSTFIELDS | POST データを指定。配列を渡すと application/x-www-form-urlencoded になる | string | array | なし |
CURLOPT_HTTPHEADER | 任意の HTTP ヘッダーを送信。ヘッダーが1行だけでも配列で指定 | array | なし |
CURLOPT_TIMEOUT | 全体のリクエスト処理の最大時間(接続・送信・受信すべて含む)(秒) | int | 0(無制限) |
CURLOPT_CONNECTTIMEOUT | 接続が確立されるまでの最大待機時間(DNS解決など)(秒) | int | 0(無制限) |
CURLOPT_FOLLOWLOCATION | HTTP リダイレクトが発生した場合に、リダイレクトを自動的に追跡 | bool | false |
CURLOPT_SSL_VERIFYPEER | SSL 証明書の検証を行う | bool | true |
CURLOPT_USERPWD | ユーザー名とパスワード | string | なし |
戻り値
成功した場合に true を、失敗した場合に false を返します。
注意点
不正なオプションや値を指定すると curl_setopt() は false を返しますが、エラーは発生しません。
また、CURLOPT_RETURNTRANSFER を true にしないと、取得内容が echo でそのまま出力されてしまうため注意が必要です。
curl_setopt_array()
curl_setopt_array() は、curl_setopt() を複数回使う代わりに、一度にまとめてオプションを設定できる関数です。可読性が高いため、複雑なリクエストでは便利です。以下が書式です。
curl_setopt_array(CurlHandle $handle, array $options): bool
パラメータ | 説明 |
---|---|
$handle | curl_init() で作成した cURL セッションハンドル。 |
$options | CURLOPT_定数 => 値 の連想配列(設定するオプションとその値を指定した配列)。 |
連想配列のキーは CURLOPT_ から始まる定数名(文字列ではなく定数)で指定する必要があります。
以下は使用例です。
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Accept: application/json'
],
CURLOPT_POSTFIELDS => json_encode($data),
CURLOPT_TIMEOUT => 10,
]);
上記は以下と同じことです。
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json; charset=UTF-8',
'Accept: application/json',
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
ヘッダー
CURLOPT_HTTPHEADER を使って HTTP ヘッダーを送信することができます。
ヘッダーが1行だけでも、CURLOPT_HTTPHEADER では配列で Name: value の形式で指定する必要があります。
// 1行だけでも配列で指定
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json'
]);
// または curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
以下は代表的な HTTP ヘッダーとその基本的な役割です。
ヘッダー名 | 用途 |
---|---|
Accept | クライアントが受け取りたいレスポンスの形式を示す(例:application/json) |
Content-Type | クライアントが送信するデータの形式を示す(例:application/json や application/x-www-form-urlencoded) |
Authorization | 認証情報(APIキー、Bearer トークンなど)を送信する |
User-Agent | ブラウザやクライアントの名前をサーバーに伝える(任意) |
カスタムヘッダー
HTTP 通信では「独自のヘッダー(カスタムヘッダー)」を自由に定義して送信することが可能です。例えば、X-API-Key はその一例で、API 認証などの目的でよく使われています。
カスタムヘッダーとは、標準で定義されていない HTTP ヘッダーで、独自の用途で送信されるものです。
例:
- X-API-Key: abc123xyz
- X-Client-Version: 1.2.3
- X-User-Token: xyz789
昔は「X-」プレフィックスを付けるのが慣例でしたが、現在は RFC により X- は非推奨とされ、独自ヘッダーでも X- を省く場合が増えています。
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'X-API-Key: your_api_key_here', // カスタムヘッダー
'Content-Type: application/json',
]);
カスタムヘッダー使用の注意点
- クライアントとサーバーの両方がそのヘッダーの意味を理解している必要があります
- CORS(クロスオリジン)通信時には、カスタムヘッダーが「プリフライトリクエスト」に影響することがあるため、サーバー側でも明示的に許可する必要があります
JSON を POST する場合
以下は cURL でヘッダーを指定して JSON データを POST 送信する例です。
POST 送信するので CURLOPT_POST に true を設定し、CURLOPT_POSTFIELDS に JSON エンコードした JSON 文字列を指定して送信しています。
ヘッダーでは、Content-Type に送信するデータの形式として application/json を、Accept に受け取りたいレスポンスの形式として application/json を指定しています。
$data = [
'title' => 'Foo',
'body' => 'Lorem ipsum dolor sit amet consectetur adipisicing elit.',
'userId' => 1,
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://jsonplaceholder.typicode.com/posts");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); // JSON エンコードして送信
// ヘッダーを設定
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json', // 送信データの形式
'Accept: application/json', // 期待するレスポンス形式
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
オプションの設定は curl_setopt_array() を使って以下のように記述することもできます。
curl_setopt_array($ch, [
CURLOPT_URL => "https://jsonplaceholder.typicode.com/posts",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
// ヘッダーを設定
CURLOPT_HTTPHEADER => [
'Content-Type: application/json', // 送信データの形式
'Accept: application/json', // 期待するレスポンス形式
],
CURLOPT_POSTFIELDS => json_encode($data), // JSON エンコードして送信
]);
フォーム形式で POST する場合
以下は送信するデータ(連想配列)を http_build_query() を使ってクエリ文字列(URL エンコード形式)に変換して送信する場合の例です。
ヘッダーでは、Content-Type に送信するデータの形式として application/x-www-form-urlencoded を指定します。
$data = [
'title' => 'Foo',
'body' => 'Lorem ipsum dolor sit amet consectetur adipisicing elit.',
'userId' => 1,
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://jsonplaceholder.typicode.com/posts");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data)); // クエリ形式で送信
// ヘッダーを設定
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/x-www-form-urlencoded', // 送信データの形式
'Accept: application/json', // 期待するレスポンス形式
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
Content-Type に指定できる値(送信データの形式)
以下は代表的な Content-Type の値です。
値 | 用途・説明 |
---|---|
application/json | JSON形式のデータ(APIで最も一般的) |
application/json; charset=UTF-8 | JSON は UTF-8 が標準ですが、日本語を含むデータを POST する場合や、より堅牢な実装を目指す場合には付けておくのが安心 |
application/x-www-form-urlencoded | フォーム形式のデータ(key=value&... 形式、POSTフォームに相当) |
multipart/form-data | ファイルアップロード(HTMLフォームの enctype="multipart/form-data") |
text/plain | プレーンテキスト形式 |
application/xml | XML形式のデータ |
application/octet-stream | バイナリデータの送信(ファイルなど) |
text/html | HTML文書(通常は送信に使われない) |
Accept に指定できる値(受け取りたいレスポンスの形式)
以下は代表的な Accept の値です。
値 | 用途・説明 |
---|---|
application/json | JSONレスポンスを要求(APIで一般的) |
application/xml | XMLレスポンスを要求 |
text/html | HTMLレスポンス(ブラウザのデフォルト) |
text/plain | プレーンテキストレスポンスを要求 |
*/* | すべての形式を受け入れる(何でもOK) |
curl_exec()
curl_exec() は、初期化して設定済みの cURL セッションを実行する関数で、実際の HTTP リクエストを送信し、レスポンスを受け取る処理を行います。
この関数は、cURL セッションを初期化し、 オプションを全て設定した後にコールする必要があります。
curl_exec(CurlHandle $handle): string|bool
- $handle は curl_init() で生成した cURL セッションハンドル。
- 実行されたリクエストの結果は、設定により次のように返されます:
- CURLOPT_RETURNTRANSFER が true → レスポンス文字列。失敗時は false
- CURLOPT_RETURNTRANSFER が false → 直接出力され、戻り値は true/false
戻り値の解釈
- 成功時: レスポンス文字列、または true を返す
- 失敗時: false を返す
curl_exec() が false を返す理由
curl_exec() が false を返す主な理由は以下の 3 つのケースに分類されます。
- 通信レベルのエラー(cURL がサーバーにアクセスできなかった)
- DNS 解決失敗:CURLE_COULDNT_RESOLVE_HOST (6)
- 接続失敗:CURLE_COULDNT_CONNECT (7)
- タイムアウト
- 接続:CURLE_OPERATION_TIMEOUTED (28)
- 応答読み込み:CURLE_RECV_ERROR (56) など
- SSL エラー:CURLE_SSL_CONNECT_ERROR (35), CURLE_PEER_FAILED_VERIFICATION (51)
- 通信前の設定ミス(リクエストの構成が不正)
- URL 書式不正:CURLE_URL_MALFORMAT (3)
- POST フィールドの不正、読み込みエラー:CURLE_READ_ERROR (26)
- ログイン失敗(FTP/SMTP など):CURLE_LOGIN_DENIED (67)
- ヘッダーサイズオーバー:CURLE_TOO_MANY_REDIRECTS (47) など
- CURLOPT_FAILONERROR による false(意図的な false)※以下参照
- curl_setopt() で CURLOPT_FAILONERROR を true に設定すると、通信自体は成功しても、HTTP ステータスコード(例: 404, 500)が 400 以上の場合に false を返します。この場合のエラーコードは、CURLE_HTTP_RETURNED_ERROR (22)
※ 404 Not Found や 500 Internal Server Error
デフォルトでは、HTTP ステータスコードが 400 以上(例: 404, 500)の場合や 200 未満の場合、通信自体は成功したとみなして、curl_exec() は false を返しません。
そのため、エラー判定をする際は、curl_exec() が false を返すかだけでなく、ステータスコードも確認する必要があります。詳細は エラーハンドリング を参照。
curl_close()
curl_close() は、cURL セッションを閉じてリソースを解放する関数で、cURL ハンドルも削除されます。
curl_init() で作成した $ch を使い終わったら、curl_close($ch) を呼ぶのが基本です(※ PHP 7.x 以前)。
curl_close(CurlHandle $handle): void
- $handle は curl_init() で生成した cURL セッションハンドル。
- 戻り値:なし(void)
PHP 8.0 以降の場合
バージョン | curl_init() の戻り値(cURL ハンドル) | curl_close() の役割 |
---|---|---|
PHP 7.x 以前 | リソース(resource 型) | リソースを明示的に開放する |
PHP 8.0 以降 | オブジェクト(CurlHandle クラス) | 不要。オブジェクト破棄時に自動で開放される |
PHP 8.0 以降では、cURL ハンドルはオブジェクトなので、PHP のガベージコレクション(自動メモリ解放)により、自動的に解放されます。そのため、curl_close() を呼んでも実際には何も処理されません。
curl_close() は今でも書くべきか?
以下の理由から書いておくのが推奨されます。
- PHP 7.x 以前との互換性のため
- コードの明示性・明快さのため(意図が読みやすい)
PHP 8 以降では curl_close() は実質「何もしない関数」ですが、書いても害はなく、保守性が上がるため推奨されます。PHP 8.0 以降専用のコードを書くケースでは省略も可能です。
エラーハンドリング
cURL でエラーハンドリングを行うには、「通信エラー」や「HTTP ステータスコードによるエラー」をキャッチして対応します。以下が基本的なエラーハンドリングの流れになります。
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://example.com/api");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
// curl_exec() の戻り値で通信成功かどうか判定(ネットワーク、タイムアウトなど)
if ($response === false) {
// 明確な失敗。cURLレベルの通信障害があった可能性が高い
echo "cURL エラー番号: " . curl_errno($ch) . "<br>";
echo "エラーメッセージ: " . curl_error($ch);
} else {
// 成功しても HTTP エラーの可能性があるのでステータスコード(整数値)をチェック
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($httpCode < 200 || $httpCode >= 400) {
// 200 未満または400以上はエラーとみなす
echo "HTTP エラーまたは予期しないステータス: $httpCode";
} else {
echo "成功: $response";
}
}
curl_close($ch);
- curl_exec() の戻り値でエラーが起きたか確認。
- curl_error() や curl_errno() でエラー内容やエラー番号を確認(表示)
- curl_getinfo() で HTTP ステータスコードを確認し、200 未満または400以上なら HTTP エラー
まず、curl_exec() の戻り値を確認し、false ならエラーと判定できます。
但し、curl_exec() が false でなくても、HTTP 的には 404 Not Found や 500 Internal Server Error などのエラーである可能性があるので、別途 curl_getinfo() でステータスコードをチェックする必要があり、ステータスコードが 400 以上の場合は HTTP エラーと判定します。
curl_getinfo($ch, CURLINFO_HTTP_CODE) で返されるステータスコードは整数(int)です。
範囲 | 名称 | 概要 |
---|---|---|
100-199 | Informational(情報) | リクエストは受け取ったが処理は未完了 |
200-299 | Success(成功) | リクエストは正常に処理された |
300-399 | Redirection(リダイレクト) | 別URLへ移動するよう指示 |
400-499 | Client Error(クライアントエラー) | リクエストに問題あり |
500-599 | Server Error(サーバーエラー) | サーバー側のエラー |
コード | 意味 | 用途・備考 |
---|---|---|
200 | OK | 一般的な成功 |
201 | Created | リソース作成成功(POST) |
204 | No Content | 成功だが本文なし(DELETE等) |
301 | Moved Permanently | 恒久的なリダイレクト |
302 | Found | 一時的なリダイレクト |
400 | Bad Request | 構文ミスや不正パラメータ |
401 | Unauthorized | 認証が必要 |
403 | Forbidden | アクセス権がない |
404 | Not Found | リソースが存在しない |
500 | Internal Server Error | サーバー内部エラー |
502 | Bad Gateway | ゲートウェイやプロキシのエラー |
503 | Service Unavailable | 一時的な利用不可 |
curl_errno()
curl_errno() は PHP の cURL 関数でエラーが発生した際に、エラー番号(int型)を取得する関数です。
curl_errno(CurlHandle $handle): int
- $ch は curl_init() で取得した cURL セッションハンドルです。
- 戻り値は整数のエラーコード。0 はエラーなし。それ以外は何らかのエラーを意味します。
- エラーの内容(メッセージ)を知りたい場合は curl_error($ch) を使います。
コード | 定数名 | 意味 |
---|---|---|
0 | CURLE_OK | 正常終了 |
6 | CURLE_COULDNT_RESOLVE_HOST | ホスト名解決失敗 |
7 | CURLE_COULDNT_CONNECT | 接続に失敗 |
28 | CURLE_OPERATION_TIMEDOUT | 処理がタイムアウト |
35 | CURLE_SSL_CONNECT_ERROR | SSL 接続エラー |
60 | CURLE_SSL_CACERT | CA証明書の検証に失敗 |
67 | CURLE_LOGIN_DENIED | FTP/SMTP などのログイン失敗 |
curl_error()
curl_error() は PHP の cURL 関数において、直近のエラーのメッセージ(文字列)を取得する関数です。
curl_error(CurlHandle $handle): string
- $ch は curl_init() で作成した cURL セッションハンドル。
- 戻り値はエラーメッセージ(string)。エラーがなければ空文字 '' を返します。
curl_errno($ch) が 0 以外(=何らかのエラー)だったときに、その具体的な原因を知るために使います。
curl_getinfo()
curl_getinfo() は PHP の cURL セッションに関する実行結果の詳細情報を取得するための関数です。
curl_getinfo(CurlHandle $handle, ?int $option = null): mixed
- $ch は curl_init() で作成した cURL セッションハンドル。
- $option:
- 省略:すべての情報を連想配列で取得
- 指定:特定の情報のみ取得(例:CURLINFO_HTTP_CODE)
- 戻り値は $option を指定した場合はその値を返し、省略した場合はすべての情報の要素をもつ連想配列を返します。失敗した場合は false を返します。
情報は curl_exec() 実行後 でなければ取得できません。
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://example.com/");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
// HTTP ステータスコードを取得
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
// レスポンスヘッダーの Content-Type を取得
$contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
// DNS解決にかかった時間
$dnsTime = curl_getinfo($ch, CURLINFO_NAMELOOKUP_TIME);
// 接続にかかった時間
$connectTime = curl_getinfo($ch, CURLINFO_CONNECT_TIME);
// リクエスト全体にかかった時間
$totalTime = curl_getinfo($ch, CURLINFO_TOTAL_TIME);
// 結果出力(例)
echo "HTTP ステータス: $httpCode<br>"; // HTTP ステータス: 200
echo "レスポンス Content-Type: $contentType<br>"; // レスポンス Content-Type: text/html
echo "DNS解決にかかった時間: $dnsTime<br>"; // DNS解決にかかった時間: 0.000887
echo "接続にかかった時間: $connectTime<br>"; // 接続にかかった時間: 0.13797
echo "リクエスト全体にかかった時間: $totalTime<br>"; // リクエスト全体にかかった時間: 0.640814
以下は curl_getinfo() で取得できる代表的な情報一覧です。
これらの情報を使ってレスポンスのデータ形式(Content-Type)を調べたり、パフォーマンス測定、リダイレクト検知などにも使えます
定数 | 意味 | 戻り値の型 | 例 |
---|---|---|---|
CURLINFO_HTTP_CODE | HTTPステータスコード | int | 200, 201, 404, 500 など |
CURLINFO_EFFECTIVE_URL | 実際にアクセスされたURL(リダイレクト後を含む) | string | https://example.com/final |
CURLINFO_CONTENT_TYPE | レスポンスのContent-Type | string | null | application/json; charset=utf-8 |
CURLINFO_TOTAL_TIME | リクエスト全体にかかった時間(秒) | float | 0.235 |
CURLINFO_NAMELOOKUP_TIME | DNS解決にかかった時間(秒) | float | 0.005 |
CURLINFO_CONNECT_TIME | 接続(DNS解決後のTCP接続確立)にかかった時間(秒) | float | 0.012 |
CURLINFO_STARTTRANSFER_TIME | 転送開始までの時間(秒) | float | 0.020 |
CURLINFO_REDIRECT_COUNT | リダイレクト回数 | int | 2 |
CURLINFO_REDIRECT_URL | リダイレクト先URL(もしあれば) | string | null | https://example.com/next |
CURLINFO_SIZE_DOWNLOAD | ダウンロードされたデータのサイズ(バイト) | float | 5123.0 |
CURLINFO_HEADER_SIZE | レスポンスヘッダーのバイト数 | int | 342 |
CURLINFO_HTTP_CODE の値は、成功時は 200, 201, 404, 500 など、HTTP のステータスコード(int型)が返りますが、DNS 解決失敗時やネットワーク接続失敗時(タイムアウトなど)には 0 になります。また、意図せず curl_close() した後に取得すると null になることがあります。
レスポンスが JSON の場合
以下はレスポンスが JSON の場合の GET リクエストの例で、レスポンスの JSON 文字列を json_decode() で第2引数に true を指定して PHP の配列に変換しています。
json_decode() はエラーが起きても警告や例外を出さず、false を返すのみなので、必ず json_last_error() で検証するのが推奨される手順です。json_last_error_msg() を使うとエラー文字列を取得できます。
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://jsonplaceholder.typicode.com/posts/1");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
if ($response === false) {
echo "cURL エラー番号: " . curl_errno($ch) . "<br>";
echo "エラーメッセージ: " . curl_error($ch);
} else {
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
// 成功時の処理
if ($httpCode === 200) {
// JSON 文字列を PHP の配列に変換
$json = json_decode($response, true);
// JSON を検証
if (json_last_error() === JSON_ERROR_NONE) {
// JSON 解析でエラーなし
print_r($json); // または echo $json['body']; など
} else {
echo "JSONの解析に失敗しました: " . json_last_error_msg();
}
} else {
echo "HTTP エラーまたは予期しないステータス: $httpCode";
}
}
curl_close($ch);
JSON が不正になる可能性(典型例)
- レスポンスが HTML やテキスト(API 側のエラーメッセージなど)だった。
- 文字コードに問題があった。
- ネットワーク障害などで部分的な JSON が返った。
リクエストサンプル
cURL を使った GET リクエストと POST リクエストのサンプルです。
GET リクエスト
以下は、{JSON} Placeholder というテスト用の JSON データを返す API にアクセスして取得したレスポンスを出力する例です。「/posts/1」にアクセスすると ID が1の投稿のデータ(JSON)を取得できます。
この例の場合、{JSON} Placeholder は Accept ヘッダーが未指定でも JSON を返すように設計されているので、Accept ヘッダーは省略可能ですが、本番環境・汎用的なコードでは Accept ヘッダーを付けておくのが無難です。
$url = 'https://jsonplaceholder.typicode.com/posts/1';
$ch = curl_init($url);
// オプション設定
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 結果を文字列で受け取る
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Accept: application/json']); // ヘッダー指定
curl_setopt($ch, CURLOPT_TIMEOUT , 10); // タイムアウト秒数
$response = curl_exec($ch);
// ステータスコード取得
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
// エラー確認
if ($response === false) {
echo 'cURL エラー: ' . curl_error($ch);
} elseif ($httpCode === 200) {
// JSON 文字列を PHP の配列に変換
$json = json_decode($response, true);
if (json_last_error() === JSON_ERROR_NONE) {
// 出力
print_r($json);
} else {
echo "JSONの解析に失敗しました: " . json_last_error_msg();
}
} else {
echo "GET失敗: HTTPステータス " . $httpCode . "\n";
}
curl_close($ch);
URL パラメータ
以下は http_build_query() を使ってパラメータをクエリ文字列に変換して URL に追加してリクエストする例です。また、カスタムヘッダー(X-API-Key)で API キーを指定しています。
$baseUrl = "https://example.com/wp/wp-json/wp/v2/posts";
// URL に追加するクエリパラメータ
$params = [
'_fields' => 'title,link',
'per_page' => 3,
];
// パラメータをクエリ文字列に変換して URL に追加
$url = $baseUrl . '?' . http_build_query($params);
$api_key = 'abc123def456'; // API キー(実際の運用ではAPIキーを別ファイルで管理する)
// cURL セッションを初期化
$ch = curl_init($url);
// オプションをまとめて設定
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"X-API-Key: $api_key",
"Content-Type: application/json",
],
CURLOPT_TIMEOUT => 10,
]);
// 実行とエラーチェック
$response = curl_exec($ch);
$curlError = curl_error($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
// セッション終了
curl_close($ch);
// 結果処理
if ($response === false) {
echo "cURLエラー: $curlError";
} elseif ($httpCode === 200) {
$json = json_decode($response, true);
if (json_last_error() === JSON_ERROR_NONE) {
print_r($json);
} else {
echo "JSONの解析に失敗しました: " . json_last_error_msg();
}
} else {
echo "GET失敗: HTTPステータス $httpCode\n";
}
API キーを Authorization ヘッダーで指定する場合は、例えば以下のように CURLOPT_HTTPHEADER オプションを変更します。以下は Bearer 認証形式の場合の例です。
CURLOPT_HTTPHEADER => [
"Authorization: Bearer $api_key", // "X-API-Key: $api_key" から変更
"Content-Type: application/json",
],
APIキーを別ファイルで管理
前述の例では、API キーをコードに直接記述していましたが、以下は config というフォルダを作成し、その中に .htaccess と API キーを定義した config.php というファイルを作成して管理する例です。
.htaccess に以下を記述し、Web 経由では config.php にアクセスできないようにします。
# /config/.htaccess
Order deny,allow
Deny from all
Apache 2.4 以降では以下のように記述します。
# Apache 2.4+
Require all denied
config.php に API キーを定義します。
<?php
// API キーを定義(絶対に何も出力しない)
define('API_KEY', 'abc123def456');
API キーを require_once で読み込みます。
以下では curl_setopt_array() の代わりに curl_setopt() を使っていますが、特に意味はありません。
// API キーを読み込む
require_once __DIR__ . '/config/config.php';
$baseUrl = "https://example.com/wp/wp-json/wp/v2/posts";
$params = [
'_fields' => 'title,link',
'per_page' => 3,
];
$url = $baseUrl . '?' . http_build_query($params);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"X-API-Key: " . API_KEY, // 読み込んだ API キーを指定
"Content-Type: application/json",
]);
curl_setopt($ch, CURLOPT_TIMEOUT , 10);
$response = curl_exec($ch);
$curlError = curl_error($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($response === false) {
echo "cURLエラー: $curlError";
} elseif ($httpCode === 200) {
$json = json_decode($response, true);
if (json_last_error() === JSON_ERROR_NONE) {
print_r($json);
} else {
echo "JSONの解析に失敗しました: " . json_last_error_msg();
}
} else {
echo "GET失敗: HTTPステータス $httpCode\n";
}
POST リクエスト
以下は JSON 形式、URL エンコード形式でデータを送信する POST リクエストのサンプルです。
JSON 形式
以下は JSON 形式(application/json)でデータを送信するサンプルです。
JSON 形式でデータを送信するので、Content-Type に application/json を指定し、Accept ヘッダー(受け取りたいレスポンスの形式)には application/json を指定しています。
また、JSON は UTF-8 が標準ですが、この例では Content-Type: application/json; charset=UTF-8 のように charset を明示的に指定しています(charset=UTF-8 は省略可能)。
成功判定はステータスコードが 201 Created かどうかで確認しています。
$url = 'https://jsonplaceholder.typicode.com/posts';
$data = [
'title' => 'Foo',
'body' => 'Lorem ipsum dolor sit amet consectetur adipisicing elit.',
'userId' => 1,
];
// JSON に変換
$jsonData = json_encode($data);
// cURL 初期化
$ch = curl_init();
// オプション設定
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_POST => true, // POST メソッドを使用
CURLOPT_POSTFIELDS => $jsonData, // JSON を指定
CURLOPT_HTTPHEADER => [
'Content-Type: application/json; charset=UTF-8', // Content-Type: application/json を指定
'Accept: application/json',
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
]);
// 実行
$response = curl_exec($ch);
// ステータスコード取得
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
// エラーハンドリング
if ($response === false) {
echo "cURL エラー: " . curl_error($ch);
} elseif ($httpCode === 201) { // JSONPlaceholder は成功時に 201 を返す
$json = json_decode($response, true);
if (json_last_error() === JSON_ERROR_NONE) {
echo "送信成功:\n";
print_r($json);
} else {
echo "JSON解析エラー: " . json_last_error_msg();
}
} else {
echo "送信失敗: HTTPステータス $httpCode\n";
echo "レスポンス内容:\n$response";
}
curl_close($ch);
URL エンコード形式
以下は URL エンコード形式でデータを送信する POST リクエストのサンプルです。
送信するデータを http_build_query() で URL エンコード形式に変換して content に指定しています。この例では RFC3986準拠のエンコードでクエリ文字列を生成しています。
CURLOPT_POSTFIELDS に URL エンコードされた文字列を渡すと、自動で Content-Type を application/x-www-form-urlencoded に設定するケースもありますが、明示的に設定するのが安全です。
また、Content-Length も省略可能ですが、サーバーによっては必要な場合があるため指定してあります。
https://httpbin.org/ はテスト用のサービスです。
$url = 'https://httpbin.org/post'; // テスト用エコーサービス
// 送信データ(連想配列)
$data = [
'name' => 'John Doe',
'email' => 'john@example.com',
'message' => 'こんにちは',
];
// 送信データを URL エンコード形式に変換
$postData = http_build_query($data, '', '&', PHP_QUERY_RFC3986);
// cURL 初期化
$ch = curl_init($url);
// オプション設定
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $postData,
CURLOPT_HTTPHEADER => [
'Content-Type: application/x-www-form-urlencoded',
'Content-Length: ' . strlen($postData),
],
CURLOPT_TIMEOUT => 10,
]);
// 実行
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
// エラーチェック
if ($response === false) {
echo "cURL エラー: " . curl_error($ch);
} elseif ($httpCode >= 200 && $httpCode < 300) {
echo "送信成功:\n";
echo $response;
} else {
echo "送信失敗: HTTPステータス $httpCode\n";
echo "レスポンス:\n$response";
}
// 終了処理
curl_close($ch);
補足
CURLOPT_POSTFIELDS に URL エンコードされた文字列 を渡した場合、PHP の cURL は自動的に Content-Type: application/x-www-form-urlencoded を付与します。
同様に、Content-Length も自動で計算されます。
つまり、オプション設定を以下のように CURLOPT_HTTPHEADER を省略しても問題なく動作します。
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $postData,
CURLOPT_TIMEOUT => 10,
]);
但し、以下の場合は CURLOPT_HTTPHEADER を自分で指定する必要があります。
- Content-Type を application/json や multipart/form-data などに変更したい場合
- 特定の API キーや認証トークンを Authorization ヘッダーなどで送信したい場合
レスポンスの Content-Type を取得
$response のデータ形式(文字列の構造や内容)は、サーバー側の実装に依存します。
この例の https://httpbin.org/post のエンドポイントの場合、POST された内容を JSON 形式で返すことがわかっているので、$response を json_decode() すれば、配列として扱えます。
必要に応じて curl_getinfo() でレスポンスのデータ形式を確認することができます。
以下はレスポンスの Content-Type を取得するコード例です。
curl_getinfo($ch, CURLINFO_CONTENT_TYPE) でレスポンスの Content-Type を取得し、JSON 形式かどうかを strpos($contentType, 'application/json') でチェックしています。
$ch = curl_init('https://httpbin.org/post');
$data = [
'name' => 'John Doe',
'email' => 'john@example.com',
'message' => 'こんにちは',
];
$postData = http_build_query($data, '', '&', PHP_QUERY_RFC3986);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $postData,
CURLOPT_TIMEOUT => 10,
]);
$response = curl_exec($ch);
// レスポンスヘッダーの Content-Type を取得
$contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// 結果出力(確認用)
echo "HTTP ステータス: $httpCode<br>";
echo "レスポンス Content-Type: $contentType<br>";
if ($httpCode >= 200 && $httpCode < 300) {
// JSON 形式の場合はデコードして出力
if (strpos($contentType, 'application/json') !== false) {
$json = json_decode($response, true);
if (json_last_error() === JSON_ERROR_NONE) {
echo "<pre>";
print_r($json);
echo "</pre>";
} else {
echo "JSON解析エラー: " . json_last_error_msg();
}
} else {
echo "レスポンス:\n$response";
}
} else {
echo "送信失敗"; // エラーレスポンスも表示する場合は echo "送信失敗:\n$response";
}
httpbin.org
https://httpbin.org は、HTTP リクエストのテストとデバッグ用に使える無料の Web サービスです。開発者が HTTP リクエストの送信や受信内容を確認するために利用することができます。
以下は主な特徴です。
- リクエスト内容のエコー(反映)
送信したデータ(ヘッダー、クエリパラメータ、ボディなど)をそのまま返します。 - さまざまな HTTP メソッドのテスト
GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS などすべてに対応。 - 任意のステータスコードを返すエンドポイント
/status/404 や /status/500 のように、指定したステータスコードで応答させることができます。 - レスポンスの遅延テスト
/delay/3 のように遅延させたレスポンスを返すことで、タイムアウト処理のテストが可能です。
以下は curl 経由のリクエストで API キーが正しく送信されているか確認する例です。
$apiKey = 'abc123xyz456'; // API キーを指定
$url = 'https://httpbin.org/headers'; // 送信されたヘッダーをそのまま返してくれる
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'X-API-Key: ' . $apiKey,
'Accept: application/json',
],
]);
$response = curl_exec($ch);
if ($response === false) {
echo "cURL エラー: " . curl_error($ch);
} else {
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
echo "HTTP ステータス: $httpCode\n";
// JSON 文字列を整形(整形済みの形式で見やすく)して出力(必要に応じて)
$prettyJson = json_encode(json_decode($response), JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
echo "<pre>$prettyJson</pre>";
}
curl_close($ch);
以下は実行結果の例です。レスポンスに "X-Api-Key": "abc123xyz456" が含まれていれば、正しく送信できていると判断できます。但し、送信したものをそのまま返しているだけなので、内容が正しいかどうかを判定できるわけではありません。
HTTP ステータス: 200
{
"headers": {
"Accept": "application\/json",
"Host": "httpbin.org",
"X-Amzn-Trace-Id": "Root=1-681821cc-0e26ea8e70345faa1b45bcaf",
"X-Api-Key": "abc123xyz456"
}
}
リクエスト先に https://httpbin.org/anything を使っても以下のようにヘッダー+ボディが返ります。
HTTP ステータス: 200
{
"args": {},
"data": "",
"files": {},
"form": {},
"headers": {
"Accept": "application\/json",
"Host": "httpbin.org",
"X-Amzn-Trace-Id": "Root=1-68182307-30f0c5e45d0d0df34c07c9d0",
"X-Api-Key": "abc123xyz456"
},
"json": null,
"method": "GET",
"origin": "12.3.45.678",
"url": "https:\/\/httpbin.org\/anything"
}
自分の IP アドレス
また、ブラウザで https://httpbin.org/ip にアクセスすると自分の IP アドレスが返されます。
{
"origin": "12.3.45.678"
}