## 下位互換性のない変更点

### PHP コア

#### コールスタックがオーバーフローしそうになっているプログラム

コールスタックがオーバーフローしそうになっているプログラムは、zend.max_allowed_stack_size - zend.reserved_stack_size (ファイバーの場合は fiber.stack_size - zend.reserved_stack_size) バイト以上のスタックを使い切った時点で Error をスローするようになりました。

#### proc_get_status() を複数回コールする

proc_get_status() を複数回コールした場合、POSIX システムでは常に正しい値を返すようになりました。これより前のバージョンでは、最初の呼び出しの場合にだけ正しい値を返していました。proc_get_status() をコールしたあとに proc_close() を呼び出した場合も、正しい終了コードを返すようになりました。これより前のバージョンでは、`-1` を返していました。内部的に、この処理は POSIX システム上で結果の値をキャッシュすることで実現しています。以前の振る舞いを望む場合は、proc_get_status() が返す配列の `"cached"` キーをチェックすることで、結果がキャッシュされているかを確認できます。

#### 実行時間の最大秒数を制御するタイマー

実行時間の最大秒数を制御するタイマーが、Linux 上で ZTS を有効にしてビルドした場合でもデフォルトで有効になりました。

#### static プロパティと一緒にトレイトを使う

static プロパティと一緒にトレイトを使うと、親クラスから継承する static プロパティを再宣言するようになりました。つまり、現在のクラスのために別の static プロパティを作成するということです。これは、トレイトを使わずに直接 static プロパティを追加する操作に似ています。

#### 空の配列に負のインデックスを割り当てる

空の配列に負のインデックス $n を割り当てた場合、その次のインデックスは `0` ではなく、必ず `$n+1` になります。

#### クラス定数のアクセス権

クラス定数のアクセス権が、インターフェイスから継承した場合でも正しくチェックされるようになりました。

#### キーが自分自身を参照している WeakMap のエントリ

WeakMap のエントリには、(おそらく推移的に) キーが自分自身を参照しているものがあります。そのキーが到達できない場合に、循環参照のコレクタがそれを削除できるようになりました。但し、WeakMap をループしている場合を除きます (ループ経由で到達できることは、weak と見なされるためです)。これより前のバージョンでは、こうしたエントリは自動で決して削除されませんでした。

### Date

日付・時刻の拡張モジュールでは、DateError と DateException の階層に、拡張モジュール特有の例外とエラーを追加しました。これは、エラー時に警告や汎用の例外を発生させていた動作を置き換えるものです。これらによって、エラーや例外をチェックする必要がなくなり、エラーハンドリングが改善できます。

### DOM

親が存在しないノード上で DOMChildNode::after(), DOMChildNode::before(), DOMChildNode::replaceWith() をコールしても、親子関係に関する例外をスローせず、何もしなくなりました。これは DOM の仕様が要求している振る舞いです。

ドキュメントノードが存在しない状態で DOMParentNode と DOMChildNode のメソッドを使うと、`DOM_HIERARCHY_REQUEST_ERR` DOMException をスローせず、エラーなしで動作するようになりました。これはDOMの仕様が要求している振る舞いです。

prefix を指定せずに DOMDocument::createAttributeNS() をコールすると、デフォルトの名前空間を誤って作成し、その名前空間中に属性ではなく要素を置いていました。PHP 8.3 では、このバグが修正されています。

以前のバージョンでは、DOMDocument::createAttributeNS() は、prefix が既に異なる URI で使われている場合に `DOM_NAMESPACE_ERRNAMESPACE_ERR` DOMException をスローしていました。 このバージョンからは、prefix の名前が衝突していた場合でも、異なる prefix を正しく選べるようになりました。

新しいメソッドやプロパティが DOM クラスに追加されました。ユーザー定義のクラスがこれらを継承し、メソッドやプロパティを親クラスのものと同じ名前で宣言した場合、それらの宣言には互換性がなければいけません。互換性がない宣言の場合、それを指摘するコンパイルエラーがスローされることになります。新しく実装されたメソッドやプロパティについては、新機能 のセクションと 新しく追加された関数 を参照ください。

### FFI

void 型を返すC言語の関数は、`object(FFI\CData:void) { }` ではなく、`null` を返すようになりました。

### Opcache

INI ディレクティブ opcache.consistency_checks が削除されました。この機能は tracing JIT や、inheritance cache (継承関係をキャッシュする機能) と一緒に使った場合に壊れてしまっていました。その後、このディレクティブを有効にする方法が見つからないまま、PHP 8.1.18 と 8.2.5 で無効にされました。tracing JIT と inheritance cache は両方、スクリプトが永続化された後に共有メモリを変更し、そのチェックサムを無効にする可能性があります。変更されうるポインタをスキップする変更も試みられましたが、複雑過ぎて受け入れられませんでした。以上の理由から、壊れてしまうバグを修正するのではなく、ディレクティブそのものが削除されることになりました。

### Phar

Phar クラスの定数が、型宣言するようになりました。

### 標準ライブラリ

range() 関数に対して、さまざまな変更が加えられました:

- オブジェクトやリソース、配列を境界の値として渡すと、TypeError がスローされるようになりました。
- `$step` に `0` を渡すと、よりわかりやすい ValueError がスローされるようになりました。
- 範囲が増加しているのに、`$step` に負の値を渡すと、ValueError がスローされるようになりました。
- `$step` が整数型として解釈できる float の場合、整数型として解釈するようになりました。
- 引数のいずれかが無限大または NAN の場合、ValueError がスローされるようになりました。
- `$start` や `$end` が空文字列の場合、`E_WARNING` が発生するようになりました。値そのものが `0` にキャストされる動作は変更されていません。
- `$start` や `$end` が1バイトより長い場合、`E_WARNING` が発生するようになりました。但し、それが数値形式の文字列でない場合に限ります。
- `$start` や `$end` が整数型にキャストした値の場合、`E_WARNING` が発生するようになりました。なぜなら、他の境界の入力値は数値だからです。(例: `range(5, 'z');`)
- `$step` が float の場合で、ある範囲の文字を生成しようとした場合、`E_WARNING` が発生するようになりました。但し、境界の値がともに数値形式の文字列の場合を除きます。(例: `range('5', '9', 0.5);` のようなコードは、警告が発生しません)
- range() 関数は、境界の値の一方が数字の場合、もう片方の境界の値を整数にキャストせず、文字のリストを生成するようになりました。(例: `range('9', 'A');`).

    <?php
    range('9', 'A');  // PHP 8.3.0 以降は、["9", ":", ";", "<", "=", ">", "?", "@", "A"]
    range('9', 'A');  // PHP 8.3.0 より前は、[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
    ?>

number_format() は、負の `$decimals` の値を小数点以下 `$num` 桁から `abs($decimals)` 桁に丸めるようになりました。 これより前のバージョンでは、負の `$decimals` は黙って無視されていました。

file() 関数の flags パラメータは、すべての不正な値をチェックするようになりました。注意すべきなのは、これより前のバージョンでは `FILE_APPEND` を黙って受け入れていましたが、このバージョンから受け入れなくなったことです。

### SNMP

SNMP クラスの定数が、型宣言するようになりました。

`↑` and `↓` to navigate • `Enter` to select • `Esc` to close • `/` to open