PHPのexit()は関数ではなく言語構造です。
という話は有名なのですが、PHP8.4でこれが変わります。
以下は該当のRFC、Transform exit() from a language construct into a standard functionの紹介です。
PHP RFC: Transform exit() from a language construct into a standard function
Introduction
言語構造exitおよびエイリアスdieは、括弧なしの単体で使用して、PHPスクリプトをステータスコード0で終了します。
もしくは引数$statusを受け入れる関数のように記述することもできます。
その場合、PHPは引数が整数であればそれをステータスコードとして終了し、文字列であれば文字をSTDOUTに出力しつつステータスコードは0で終了します。
しかし、exit()は実際は関数ではないので名前付き引数を使うことはできず、callableに渡すこともできず、strict_typesに従うこともありません。
さらに紛らわしいことに、本来の型引数のセマンティクスにも従いません。
すなわち、整数以外の引数は全てstringにキャストされます。
配列やリソースを渡してもエラーにならず、文字列ArrayやResource id #%dが出力されます。
StringableでないオブジェクトであればようやくTypeErrorになります。
またbool型はintではなくstringにキャストされるので、trueが1、falseが0にキャストされるだろうという常識に反しています。
PHP8.0以降exit()はcatchできずfinallyも実行しない特殊な例外をスローすることがあります。
最後に、exit()はわざわざ専用のオペコードを使っていますが、必要なさそうです。
Proposal
exit()を、以下のシグネチャを持つ通常の関数に変更します。
function exit(string|int $status = 0): never {}
コンパイル時は、オペコードZEND_EXITになるのではなく、関数呼び出しにコンパイルされます。
名前空間でexitという名前の関数を定義したり、INI設定disable_functionsで無効化できないのは現状の動作のままです。
Backward Incompatible Changes
後方互換性のない変更。
このRFCの影響は小さいと考えられます。
ext()の引数の型による動作変更は以下の通り。
| 引数の型 | 現在 | 変更後 | 結果 |
|---|---|---|---|
| int | int | int | 変更なし。終了コード。 |
| string | string | string | 変更なし。終了メッセージ。 |
| bool | string | int | 終了コードに変更。 |
| float | string | int | 終了コードに変更。暗黙の変換は推奨されないE_DEPTECATEDが発生する可能性がある。 |
| null | string | int | 終了コードに変更。string |
| stringableなobject | string | string | 変更なし。終了メッセージ。 |
| stringableでないobject | TypeError | TypeError | 変更なし。 |
| array | string | TypeError | エラーに変更。 |
| resource | string | TypeError | エラーに変更。 |
Future scope
将来の展望であり、このRFCには含まれません。
・()なしの呼び出しを非推奨にする。
・finallyブロックを実行する。
・disable_functionsで無効化可能にする。
Version
PHP8.4。
Vote
賛成24反対12のちょうど2/3で受理されました。
感想
PHPの関数は括弧が必須なのですが、いきなりexit;を禁止するとなると影響があまりに大きすぎるので、本RFCではかっこつけないexit;も許可します。
もしかしたら今後どこかで削除されるかもしれませんが、いまのところその予定はないようです。
メーリングリストやプルリクエストを読んでも、どうしてそこまでしてこれを導入したかったのかは正直よくわかりませんでした。
利点はいろいろ書かれていますがほとんどは単なる仕様の話であり、関数にしたからなおるってわけでもない気がします。
オペコードZEND_EXITをなくすだけのためにこれを?
ということでPHP8.4以降、'exit'();とか$f='exit';$f();とか書けるようになります。
いやまあ、そんな書き方をすることが目的では絶対ないと思いますけどね。