24
11

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】exitが言語構造ではなくなった

Posted at

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にキャストされます。
配列やリソースを渡してもエラーにならず、文字列ArrayResource 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();とか書けるようになります。
いやまあ、そんな書き方をすることが目的では絶対ないと思いますけどね。

24
11
1

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
24
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?