結論(先に解決策)
PHP 8.5 に上げたら、HTTP クライアント周りでこの2つの Deprecated 警告が出ることがあります。
Deprecated: Function curl_close() is deprecated
Deprecated: The $http_response_header variable is deprecated since 8.5
どちらも機能は今も動く(即エラーではない)ので、慌てず次のように移行します。
| 非推奨 | 対応 |
|---|---|
curl_close($ch) |
呼び出しを削除するだけ(PHP 8.0+ で既に no-op) |
$http_response_header |
http_get_last_response_headers() を使う(PHP 8.5+)。8.4 以前はフォールバック |
// curl_close は消すだけ
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$body = curl_exec($ch);
// curl_close($ch); ← 削除。CurlHandle は GC が破棄する
// $http_response_header は関数経由に
$body = file_get_contents($url);
$headers = function_exists('http_get_last_response_headers')
? http_get_last_response_headers() // PHP 8.5+
: ($http_response_header ?? []); // 8.4 以前のフォールバック
症状
PHP 8.5 で、これまで普通に書いていたコードに Deprecated 警告が付く。
// (1) cURL を閉じる定番コード
curl_close($ch);
// Deprecated: Function curl_close() is deprecated
// (2) file_get_contents / fopen 後にレスポンスヘッダを読む定番コード
$body = file_get_contents('https://example.com/');
var_dump($http_response_header);
// Deprecated: The $http_response_header variable is deprecated since 8.5
error_reporting で E_DEPRECATED を出している環境(開発機や display_errors=On の本番)でログが警告まみれになる、というのが実害です。
原因
curl_close() — そもそも何もしていない関数になっていた
PHP 8.0 で cURL ハンドルが リソースから CurlHandle オブジェクトに変わりました。オブジェクトは参照が無くなれば GC(ガベージコレクション)が自動で破棄するため、curl_close() は 8.0 時点で実質 no-op(何もしない) になっていました。
「もう不要な関数」なので、8.5 で正式に deprecated 化された、という流れです。mysqli 等と違い、明示クローズは要りません。
$http_response_header — マジック変数の廃止方針
$http_response_header は、file_get_contents() などのストリーム経由 HTTP アクセスのレスポンスヘッダが呼び出したローカルスコープに自動で生える特殊な変数でした。
function fetch($url) {
$body = file_get_contents($url);
return $http_response_header; // どこで定義した? → PHP が勝手に注入していた
}
この「暗黙的に変数が出現する」挙動は、スコープの見通しが悪く静的解析も難しいため、PHP は関数で明示的に取得する方式(http_get_last_response_headers())へ移行することにし、マジック変数を deprecated にしました。
解決
1. curl_close() は削除する
置き換えではなく削除でOKです。残してもいい挙動はしますが、警告を消すなら消すのが正解。
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
// 明示クローズ不要。$ch がスコープを抜ければ破棄される
ハンドルを早く解放したいなら
unset($ch)で参照を切れば十分です。
2. $http_response_header はバージョン分岐で吸収する
8.5 と 8.4 以前の両方をサポートするなら、関数の有無で分岐します。ライブラリのように複数環境で動かすコードでは特に有効です。
function http_get(string $url): array {
$body = @file_get_contents($url);
if (function_exists('http_get_last_response_headers')) {
$headers = http_get_last_response_headers(); // PHP 8.5+
} else {
$headers = $http_response_header ?? []; // PHP 8.4 以前
}
return ['body' => $body, 'headers' => $headers];
}
http_get_last_response_headers() は直近の HTTP ストリームアクセスのヘッダを返すので、file_get_contents() の直後に呼ぶのは従来と同じです。
補足
- どちらも 8.5 ではまだ動く(Deprecated であって Removed ではない)ので、急いで全部直す必要はありません。ただし
E_DEPRECATEDがログを汚すので、アップグレード時にまとめて潰しておくと後が楽です。 -
$http_response_headerを多用しているなら、この機会に cURL か Guzzle 等の HTTP クライアントへ寄せるのも検討に値します。ヘッダ取得が明示的になり、バージョン分岐も不要になります。 - 要点は 「
curl_closeは消す、$http_response_headerはhttp_get_last_response_headers()に(8.4 以前はフォールバック)」。