10
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【PHP8.4】`$http_response_header`を取得する関数が実装される

Posted at
$dummy = file_get_contents('http://example.com');

var_dump($http_response_header); // ←なにこれ?

PHPには、予め定義されている変数がいくつかあります。
有名どころとしては$_REQUEST$_SESSION等のスーパーグローバル変数、PHPをコマンドライン実行した際に入ってくる$argc・$argvです。

そしてそれ以外にひとつだけ特殊な変数があり、HTTPラッパーを使うと唐突に$http_response_headerという変数が生えます。

非常にわかりにくいというか理解に苦しむ仕様なので、これを関数経由で取得するRFCが提出されました。
既に受理されており、PHP8.4から使用可能になります。

以下は該当のRFC、Add http_(get|clear)_last_response_headers() functionの紹介です。

PHP RFC: Add http_(get|clear)_last_response_headers() function

Introduction

PHPのストリーム層を通じてHTTPリクエストを実行したとき、すなわちHTTPラッパーを使用したときに、変数$http_response_headerがどこからともなく湧いて出てきます。
よくある例としてはfile_get_contents()を使ったときです。

$http_response_headerには、HTTPラッパー経由で実行したリクエストのHTTPヘッダが含まれます。
ローカルスコープに変数を生成するという動作は追加情報を得るための最もひどい方法のひとつであるため、$php_errormsgなど類似の機能は削除されつつあります。
この変数もPHP8.1で非推奨にしたいという話はありましたが、当時は適切な代替手段がなかったため提案の対象外になりました。

ここでは、$php_errormsgを置き替えたerror_get_last()/error_clear_last()と同様に、$http_response_headerを置き替える関数を提案します。

Motivation

関数を導入する主な目的は、変数$http_response_headerをいずれ削除するためです。

この変数を作成するためにエンジン関数zend_set_local_var_str()が使われています。
$http_response_headerは、この関数とその兄弟zend_set_local_var()を今なお使用している唯一の変数です。

さらにこの変数はopcacheやJIT環境では個別に特殊な処理が必要であるため、opcache下では挙動が変わってしまう可能性があります。

この機能の削除による影響については、Backward Incompatible Changesを参照してください。

Proposal

2つの関数http_get_last_response_header(): ?arrayhttp_clear_last_response_header(): voidを追加します。

http_get_last_response_header()は、$http_response_headerと同じHTTPヘッダの内容を返します。
http_clear_last_response_header()は、HTTPヘッダをクリアします。

Backward Incompatible Changes

このRFCではまだ$http_response_headerを非推奨にしないため、下位互換性のない変更点はありません。

この機能の使用状況をExakatで分析しました。
Composerパッケージ、OSSプロジェクト等900件以上を分析したところ、30のプロジェクトで65か所が見つかりました。
使用のほとんどはGuzzleやOauth等のライブラリに由来するものでした。

$http_response_headerが削除された場合のpolyfillは不可能ですが、以下のようにすることで同じコードを使い続けることができます。

$content = file_get_contents('http://example.com/');
if (function_exists('http_get_last_response_headers')) {
    $http_response_header = http_get_last_response_headers();
}

この機能の使用頻度が少ないこと、互換のある記述が可能であること、エンジンやオプティマイザ開発の効率化を考えると、非推奨の段階を経ずに削除することも合理的かもしれません。

Version

PHP8.4。

Vote

投票期間は2024/01/29~2024/02/14、投票の2/3の賛成で受理されます。

本RFCは賛成15反対1の賛成多数で可決されました。

References

影響の出るライブラリ一覧

感想

この手の勝手に生える変数、昔はもっと存在していたのですが、register_globalsはPHP4.2で非推奨になり、$HTTP_RAW_POST_DATAはPHP5.6で非推奨になり、$php_errormsgもPHP7.2で非推奨になり、とどんどん片付けられつつあり、現在も残っているのはこの$http_response_headerと、コマンドライン実行時に入ってくる$argc・$argvだけです。
そして$http_response_headerもRFCのとおり、PHP9あたりで非推奨にされることは既定路線でしょう。

ということで最後まで残るのは$argc・$argvです。
これらについては今のところどうこうする話は出ていないようですが、いずれは他と合わせてスーパーグローバル変数$_ARGC・$_ARGVになるか、get_argc()のような関数になるかもしれませんね。

あともうひとつ気になることとしては、どうして$GLOBALSだけ_がついてないんだ。

10
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?