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

### PHP コア

#### 文字列と数値の比較

(厳密でないやり方で)数値と非数値形式の文字列を比較する場合、 数値を文字列にキャストし、文字列と比較するようになりました。 数値と数値形式の文字列の比較は、以前と同じ振る舞いをします。 注意すべきなのは、これによって、 `0 == "not-a-number"` が `false` と見なされるようになったことです。

比較 | 変更前 | 変更後
--- | --- | ---
`0 == "0"` | `true` | `true`
`0 == "0.0"` | `true` | `true`
`0 == "foo"` | `true` | `false`
`0 == ""` | `true` | `false`
`42 == " 42"` | `true` | `true`
`42 == "42foo"` | `true` | `false`

#### その他の下位互換性のない変更

- `match` が予約語になりました。

- `mixed` が予約語になりました。 よって、クラスやインターフェイス、 トレイトの名前として使えなくなっています。 名前空間の中であっても同様です。

- アサーションに失敗すると、デフォルトで例外をスローするようになりました。 古い振る舞いを望む場合、php.ini で `assert.exception=0` と設定できます。

- クラス名と同じ名前のメソッドは、コンストラクタと解釈されなくなりました。 __construct() メソッドを代わりに使って下さい。

- static でないメソッドを、staticメソッドとしてコールできる機能が削除されました。 static でないメソッドをクラス名を使ってチェックした場合、 is_callable() は失敗します。 (オブジェクトのインスタンスを使ってチェックしなければいけません)

- `(real)` と `(unset)` キャストが削除されました。

- track_errors ini ディレクティブは削除されました。 つまり、php_errormsg が利用できなくなったということです。 代わりに error_get_last() 関数が使えます。

- 大文字小文字を区別しない定数を定義できる機能が削除されました。 define() 関数の第3引数はもはや `true` ではありません。

- __autoload() 関数を使ってオートローダーを指定する機能は削除されました。 代わりに spl_autoload_register() を使うべきです。

- set_error_handler() 関数で設定されるカスタムエラーハンドラには、 `errcontext` 引数は渡されなくなりました。

- create_function() 関数は削除されました。 無名関数が代わりに使えます。

- each() 関数は削除されました。 代わりに `foreach` や ArrayIterator を使うべきです。

- Closure::fromCallable() や ReflectionMethod::getClosure() を使って メソッドから生成されたクロージャーから this の束縛を解除できる機能は削除されました。

- this を使っている適切なクロージャーから、 this の束縛を解除する機能も削除されています。

- オブジェクトに対して array_key_exists() 関数を使える機能は削除されました。 isset() または property_exists() を代わりに使えます。

- array_key_exists() 関数の引数 `key` の型に関する振る舞いが、 isset() 関数や配列アクセスの場合と一貫したものになりました。 全てのキーの型は通常の強制が行われ、配列やオブジェクトのキーは TypeError がスローされるようになりました。

- はじめの数値のキーとして n を持つ配列は、 たとえ n が負の値であっても、 次の暗黙のキーは n+1 を使うようになります。

- デフォルトの error_reporting のレベルは `E_ALL` になりました。 これより前のバージョンでは、 `E_ALL` から `E_NOTICE` と `E_DEPRECATED` が除かれていました。

- display_startup_errors は、 デフォルトで有効になりました。

- 親クラスがないクラスの内部で parent を使うと、 致命的なコンパイルエラーが発生するようになりました。

- `@` 演算子は、致命的なエラー (`E_ERROR`, `E_CORE_ERROR`, `E_COMPILE_ERROR`, `E_USER_ERROR`, `E_RECOVERABLE_ERROR`, `E_PARSE`) を隠さなくなりました。 `@` を使う時に、 error_reporting が `0` であることを期待しているエラーハンドラは、 代わりにマスクチェックを調整すべきです:

      <?php
      // こういうエラーハンドラは
      function my_error_handler($err_no, $err_msg, $filename, $linenum) {
          if (error_reporting() == 0) {
              return false;
          }
          // ...
      }

      // 以下に置き換えましょう
      function my_error_handler($err_no, $err_msg, $filename, $linenum) {
          if (!(error_reporting() & $err_no)) {
              return false;
          }
          // ...
      }
      ?>

  さらに、実運用環境で表示されていなかった、 情報のリークに繋がるエラーメッセージにも注意を払うべきです。 エラーのロギングと併せて、 `display_errors=Off` となっていることを確認するようにして下さい。

- `#[` は、コメントの開始として解釈されなくなりました。 この文法は、アトリビュート として使われるようになっているからです。

- 非互換なメソッドのシグネチャによる継承エラー(リスコフの置換原則違反)については、 常に致命的なエラーが生成されるようになりました。 これより前のバージョンでは、警告が生成される場合がありました。

- ビットシフトや加算、減算に対する連結演算子の優先順位が変更されました。

      <?php
      echo "Sum: " . $a + $b;
      // 上記は、以前のバージョンでは以下のように解釈されていました:
      echo ("Sum: " . $a) + $b;
      // PHP 8.0.0 からは、以下のように解釈されます:
      echo "Sum:" . ($a + $b);
      ?>

- 実行時に `null` に解決されるデフォルト値を持つ引数は、 引数の型を暗黙のうちに nullable とマークすることはなくなりました。 明示的に nullable と宣言するか、 明示的にデフォルト値を `null` と宣言しなければなりません。

      <?php
      // 以下のようなコードは
      function test(int $arg = CONST_RESOLVING_TO_NULL) {}
      // このように置き換えるか
      function test(?int $arg = CONST_RESOLVING_TO_NULL) {}
      // こう書きましょう
      function test(int $arg = null) {}
      ?>

- たくさんの警告が Error 例外に変換されるようになりました:

  - オブジェクトでない値にプロパティを書き込もうとした場合。 これより前のバージョンでは、 `null` については stdClass オブジェクトが暗黙のうちに作られ、 空文字列については `false` となっていました。
  - PHP_INT_MAX キーが既に使われている配列に対して、 要素を追加しようとした場合。
  - 不正な型(配列やオブジェクト) を配列のキーや文字列のオフセットとして使おうとした場合。
  - スカラー値に配列のインデックスを書き込もうとした場合
  - 配列やTraversable でない値をアンパックしようとした場合
  - 未定義の、非修飾の定数にアクセスしようとした場合。 これより前のバージョンでは、 非修飾の定数にアクセスしようとすると、警告が発生し、 文字列として解釈されていました。
  - 可変長引数でない組み込み関数に、間違った数の引数を渡した場合、 ArgumentCountError がスローされるようになりました。
  - 無効な countable 型を count() に渡した場合、 TypeError がスローされるようになりました。

  多くの notice が警告に変換されるようになりました:

  - 未定義の変数を読み取ろうとした場合
  - 未定義のプロパティを読み取ろうとした場合
  - 未定義の配列のキーを読み取ろうとした場合
  - オブジェクトでない値のプロパティを読み取ろうとした場合
  - 配列でない値のインデックスにアクセスしようとした場合
  - 配列を文字列に変換しようとした場合
  - リソースを配列のキーとして使おうとした場合
  - null や bool 値や float の値を文字列オフセットとして使おうとした場合
  - 境界を超えて文字列のオフセットを読み取ろうとした場合
  - 文字列のオフセットに空文字列を割り当てようとした場合

- 文字列のオフセットに複数バイトを割り当てようとすると、警告が発生するようになりました。

- ソースファイル中に(文字列の範囲外のNUL バイトのような) 想定外の文字が含まれていた場合、 コンパイル時に警告を出す代わりに、 ParseError がスローされるようになりました。

- 例外がキャッチされなかった場合、 "クリーンなシャットダウン" が行われます。 これは、例外がキャッチされなかった後、 デストラクタが呼ばれるということです。

- コンパイル時の致命的なエラー "Only variables can be passed by reference" は、 実行時まで遅延され、 "Argument cannot be passed by reference" という Error 例外に変換されるようになりました。

- "Only variables should be passed by reference" という警告は、 "Argument cannot be passed by reference" という例外に変換されるようになりました。

- 無名クラスのために生成される名前が変更されました。 最初の親クラスやインターフェイスの名前が含まれるようになっています:

      <?php
      new class extends ParentClass {};
      // -> ParentClass@anonymous
      new class implements FirstInterface, SecondInterface {};
      // -> FirstInterface@anonymous
      new class {};
      // -> class@anonymous
      ?>

  上で示した名前の後に、NULバイトやユニークなサフィックスが続きます。

- トレイトのエイリアス調整において、 クラス名を指定していないメソッド参照は、 曖昧でないことが必須になりました:

      <?php
      class X {
          use T1, T2 {
              func as otherFunc;
          }
          function func() {}
      }
      ?>

  `T1::func()` と `T2::func()` が両方存在している場合、 PHP 8.0.0 より前のバージョンでは、 このコードは黙って動作し、func は `T1::func` を参照するものと想定されていました。 PHP 8.0.0 からは、このコードは致命的なエラーが発生します。 `T1::func` または `T2::func` を明示的に書く必要があります。

- トレイトで定義される抽象メソッドのシグネチャは それを実装するクラスのメソッド側で、 一致しているかがチェックされるようになりました:

      <?php
      trait MyTrait {
          abstract private function neededByTrait(): string;
      }

      class MyClass {
          use MyTrait;

          // エラー。戻り値の型が一致しません。
          private function neededByTrait(): int { return 42; }
      }
      ?>

- 無効にされている関数は、存在しない関数であるかのように扱われるようになりました。 無効にされている関数を呼び出しても unknown と報告されますし、 無効にされている関数を再定義することも可能になっています。

- `data://` ストリームラッパーは書き込み可能ではなくなりました。 これは、ドキュメント化されている振る舞いに一致します。

- 算術演算子とビット演算子 `+`, `-`, `*`, `/`, `**`, `%`, `<<`, `>>`, `&`, `|`, `^`, `~`, `++`, `--` は、オペランドのひとつが配列だったり、 resource だったり、オーバーロードされていない object だったりした場合に、 一貫して TypeError をスローするようになりました。 これに対する唯一の例外は、配列と配列を `+` でマージする操作で、 これはまだサポートされています。

- float 型から文字列型へのキャストは、 ロケールに依存しないように常に振る舞うようになります。

      <?php
      setlocale(LC_ALL, "de_DE");
      $f = 3.14;
      echo $f, "\n";
      // PHP 8.0.0 より前のバージョン: 3,14
      // PHP 8.0.0 以降:        3.14
      ?>

  数値のフォーマットをカスタマイズする方法については、 printf(), number_format() 関数 および NumberFormatter() メソッドを参照ください。

- 推奨されなくなっていた、 オフセットを指定してアクセスするための波括弧のサポートが削除されました。

      <?php
      // 以下ではなく:
      $array{0};
      $array{"key"};
      // このように書いて下さい:
      $array[0];
      $array["key"];
      ?>

- private メソッドに final 修正子を指定した場合、 そのメソッドがコンストラクタでない限り、警告が発生するようになります。

- オブジェクトのコンストラクタで exit() が呼び出された場合、 オブジェクトのデストラクタはコールされなくなりました。 これは、コンストラクタが例外をスローしたときの振る舞いと一致します。

- 名前空間に含まれる名前には、 ホワイトスペースを含めることができなくなりました。 つまり、`Foo\Bar` は名前空間の名前として認識されますが `Foo \ Bar` は認識されなくなったということです。 逆に、予約語のキーワードは名前空間の一部として許されるようになりました。 これによって、コードの解釈が変わるかもしれません。 `new\x` は `constant('new\x')` と同じですが、 `new \x()` とは異なります。

- 三項演算子をネストする場合、明示的に括弧が必要になりました。

- debug_backtrace() と Exception::getTrace() メソッド は、引数にリファレンスを取らなくなりました。 これにより、バックトレースを通じて、関数の引数を変更できなくなります。

- 数値形式の文字列の扱いが、より直感的で間違いにくいものに変更されました。 ホワイトスペースが前に付いている場合の扱いと一貫性を持たせるため、 数値形式の文字列の後にホワイトスペースを付けることが許されるようになりました。 これがもっとも影響するのは以下です:

  - is_numeric() 関数
  - 文字列同士の比較
  - 型宣言
  - インクリメントとデクリメント演算

  "数値が始めに来る文字列" の概念は殆どなくなっています; このケースは、移行を容易にするために存在しています。 "A non well-formed numeric value encountered" という `E_NOTICE` が発生する文字列 は、"A non-numeric value encountered" という `E_WARNING` が発生するようになっています。 そして、"A non-numeric value encountered" という `E_WARNING` が発生していた全ての文字列は、 TypeError が発生するようになりました。 これが最も影響するのは、以下の場合です:

  - 算術演算
  - ビット演算

  この `E_WARNING` から TypeError への変更は、 不正な文字列オフセットの場合に発生する "Illegal string offset 'string'" という `E_WARNING` にも影響します。 文字列から int/float に明示的にキャストする場合の振る舞いは変更されていません

- マジックメソッドは引数と戻り値の型を持ち、 宣言された場合はチェックが行われるようになりました。 シグネチャは次の一覧と一致させるべきです:

  - `__call(string $name, array $arguments): mixed`
  - `__callStatic(string $name, array $arguments): mixed`
  - `__clone(): void`
  - `__debugInfo(): ?array`
  - `__get(string $name): mixed`
  - `__invoke(mixed $arguments): mixed`
  - `__isset(string $name): bool`
  - `__serialize(): array`
  - `__set(string $name, mixed $value): void`
  - `__set_state(array $properties): object`
  - `__sleep(): array`
  - `__unserialize(array $data): void`
  - `__unset(string $name): void`
  - `__wakeup(): void`

- call_user_func_array() 関数に渡される 配列のキーは、パラメータ名として解釈されるようになりました。 これより前のバージョンでは、静かに無視されていました。

- 名前空間の内部で `assert()` と呼ばれる関数を宣言する ことは許されなくなり、 `E_COMPILE_ERROR` が発生するようになりました。 assert() 関数は PHP エンジンによって特別扱いを受けることになっているので、 名前空間の内部で同じ名前が定義されていると、 動作が一貫しなくなる原因になるからです。

### リソースからオブジェクトへの移行

いくつかの resource が、object に移行しました。 is_resource() 関数を使って戻り値をチェックしているコードは、 `false` を返すことをチェックするコードに置き換えるべきです。

- curl_init() 関数は resource ではなく、CurlHandle オブジェクトを返すようになりました。 curl_close() 関数はもはや意味をなしません。 CurlHandle インスタンスは、 参照されなくなった場合に、自動的に破棄されます。

- curl_multi_init() 関数は resource ではなく、CurlMultiHandle オブジェクトを返すようになりました。 curl_multi_close() 関数はもはや意味をなしません。 CurlMultiHandle インスタンスは、 参照されなくなった場合に、自動的に破棄されます。

- curl_share_init() 関数は resource ではなく、CurlShareHandle オブジェクトを返すようになりました。 curl_share_close() 関数はもはや意味をなしません。 CurlShareHandle インスタンスは、 参照されなくなった場合に、自動的に破棄されます。

- enchant_broker_init() 関数は resource ではなく、EnchantBroker オブジェクトを返すようになりました。

- enchant_broker_request_dict() と enchant_broker_request_pwl_dict() 関数は resource ではなく、EnchantDictionary オブジェクトを返すようになりました。

- GD 拡張モジュールは 画像の基本的なデータ構造として resource ではなく、GdImage オブジェクトを使うようになりました。 imagedestroy() 関数はもはや意味をなしません。 GdImage インスタンスは、 参照されなくなった場合に、自動的に破棄されます。

- openssl_x509_read() と openssl_csr_sign() 関数は resource ではなく、OpenSSLCertificate オブジェクトを返すようになりました。 openssl_x509_free() 関数は非推奨となり、 もはや意味をなしません。 OpenSSLCertificate インスタンスは、 参照されなくなった場合に、自動的に破棄されます。

- openssl_csr_new() 関数は resource ではなく、OpenSSLCertificateSigningRequest オブジェクトを返すようになりました。

- openssl_pkey_new() 関数は resource ではなく、OpenSSLAsymmetricKey オブジェクトを返すようになりました。 openssl_pkey_free() 関数は非推奨となり、 もはや意味をなしません。 OpenSSLAsymmetricKey インスタンスは、 参照されなくなった場合に、自動的に破棄されます。

- shmop_open() 関数は resource ではなく、Shmop オブジェクトを返すようになりました。 shmop_close() 関数は非推奨となり、 もはや意味をなしません。 Shmop インスタンスは、 参照されなくなった場合に、自動的に破棄されます。

- socket_create(), socket_create_listen(), socket_accept(), socket_import_stream(), socket_addrinfo_connect(), socket_addrinfo_bind(), socket_wsaprotocol_info_import() 関数は resource ではなく、Socket オブジェクトを返すようになりました。 socket_addrinfo_lookup() 関数は resource ではなく、AddressInfo オブジェクトを返すようになりました。

- msg_get_queue() 関数は resource ではなく、SysvMessageQueue オブジェクトを返すようになりました。

- sem_get() 関数は resource ではなく、SysvSemaphore オブジェクトを返すようになりました。

- shm_attach() 関数は resource ではなく、SysvSharedMemory オブジェクトを返すようになりました。

- xml_parser_create() と xml_parser_create_ns() 関数は resource ではなく、XMLParser オブジェクトを返すようになりました。 xml_parser_free() 関数はもはや意味をなしません。 XMLParser インスタンスは、 参照されなくなった場合に、自動的に破棄されます。

- XMLWriter 関数 は resource ではなく、XMLWriter オブジェクトを受け入れ、返すようになりました。

- inflate_init() 関数は resource ではなく、InflateContext オブジェクトを返すようになりました。

- deflate_init() 関数は resource ではなく、DeflateContext オブジェクトを返すようになりました。

### COM および .Net (Windows)

タイプライブラリ から 大文字小文字を区別せずに定数をインポートする機能は削除されました。 com_load_typelib() 関数の第二引数は もはや `false` ではありません。 com.autoregister_casesensitive はもはや無効ではなくなりました。 つまり、com.typelib_file の #case_insensitive マーカーは無視されます。

### CURL

`CURLOPT_POSTFIELDS` は、 オブジェクトを配列として受け入れなくなりました。 オブジェクトを配列として解釈させるためには、 明示的に `(array)` キャストを行って下さい。 配列を受け入れる他のオプションにも、同じことが当てはまります。

### 日付と時刻

mktime() と gmmktime() 関数は 少なくともひとつ引数が必要になりました。 現在のタイムスタンプを取得する用途には time() 関数が使えます。

### DOM

DOM 拡張モジュールで実装されておらず、振る舞いも持たず、 テストデータもないクラスが削除されました。 これらのクラスは、最新のDOM標準からも削除されています:

- DOMNameList
- DomImplementationList
- DOMConfiguration
- DomError
- DomErrorHandler
- DOMImplementationSource
- DOMLocator
- DOMUserDataHandler
- DOMTypeInfo
- DOMStringExtend

DOM 拡張モジュールで実装されておらず、 振る舞いも持たない以下のメソッドが削除されました:

- DOMNamedNodeMap::setNamedItem()
- DOMNamedNodeMap::removeNamedItem()
- DOMNamedNodeMap::setNamedItemNS()
- DOMNamedNodeMap::removeNamedItemNS()
- DOMText::replaceWholeText()
- DOMNode::compareDocumentPosition()
- DOMNode::isEqualNode()
- DOMNode::getFeature()
- DOMNode::setUserData()
- DOMNode::getUserData()
- DOMDocument::renameNode()

### Enchant

- enchant_broker_list_dicts(), enchant_broker_describe(), enchant_dict_suggest() 関数は、 `null` ではなく、空の配列を返すようになりました。

### Exif

read_exif_data() 関数は削除されました。 exif_read_data() 関数を代わりに使うべきです。

### フィルタ

- `FILTER_VALIDATE_URL` フラグのための定数 `FILTER_FLAG_SCHEME_REQUIRED` と `FILTER_FLAG_HOST_REQUIRED` が削除されました。 `scheme` と `host` は（かつてもそうでしたが) 常に必須です。

- filter_input() 関数などで使われている定数 `INPUT_REQUEST` と `INPUT_SESSION` は削除されました。 これらは実装されたことがなく、使うと常に警告が発生していました。

### GD

- 推奨されなくなっていた image2wbmp() 関数は削除されました。

- 推奨されなくなっていた関数 png2wbmp() と jpeg2wbmp() が削除されました。

- imagecropauto() 関数の `mode` 引数のデフォルトは `-1` ではなくなりました。 `IMG_CROP_DEFAULT` を代わりに使うべきです。

- Windows では、php_gd2.dll の名前が、php_gd.dll に変更されました。

### GMP

gmp_random() 関数は削除されました。 gmp_random_range() や gmp_random_bits() 関数を代わりに使うべきです。

### Iconv

エラーが発生した時に errno を適切に設定していなかった iconv の実装はもはやサポートされなくなりました。

### IMAP

- imap_headerinfo() 関数で 未使用になっていた `default_host` 引数が削除されました。

- imap_headerinfo() 関数のエイリアスだった imap_header() 関数は削除されました。

### 国際化関数

- 推奨されなくなっていた定数 `INTL_IDNA_VARIANT_2003` が削除されました。

- 推奨されなくなっていた定数 `Normalizer::NONE` が削除されました。

### LDAP

- 推奨されなくなっていた関数 ldap_sort(), ldap_control_paged_result(), ldap_control_paged_result_response() は削除されました。

- ldap_set_rebind_proc() のインターフェイスが変更されました。 `callback` 引数は空文字列を受け入れなくなりました。 `null` を代わりに使うべきです。

### マルチバイト文字列

- INI ディレクティブ mbstring.func_overload は削除されました。 関連する定数 `MB_OVERLOAD_MAIL`, `MB_OVERLOAD_STRING`, `MB_OVERLOAD_REGEX` も削除されています。 mb_get_info() 関数の `"func_overload"` と `"func_overload_list"` エントリも削除されています。

- mb_parse_str() は、 結果の配列を指定しないと使えなくなりました。

- たくさんの mbregex の関数エイリアスが削除されました。 どの関数を代わりに使うべきなのかは、以下の一覧を参照ください:

  - mbregex_encoding() → mb_regex_encoding()
  - mbereg() → mb_ereg()
  - mberegi() → mb_eregi()
  - mbereg_replace() → mb_ereg_replace()
  - mberegi_replace() → mb_eregi_replace()
  - mbsplit() → mb_split()
  - mbereg_match() → mb_ereg_match()
  - mbereg_search() → mb_ereg_search()
  - mbereg_search_pos() → mb_ereg_search_pos()
  - mbereg_search_regs() → mb_ereg_search_regs()
  - mbereg_search_init() → mb_ereg_search_init()
  - mbereg_search_getregs() → mb_ereg_search_getregs()
  - mbereg_search_getpos() → mb_ereg_search_getpos()
  - mbereg_search_setpos() → mb_ereg_search_setpos()

- mb_ereg_replace() 関数の `e` 修正子が削除されました。 mb_ereg_replace_callback() 関数を代わりに使って下さい。

- mb_ereg_replace() 関数に文字列でないパターン引数を渡すと、 ASCII コードポイントではなく、文字列として解釈されるようになりました。 以前のバージョンの振る舞いは、 明示的に chr() 関数を呼び出すことで復元できます。

- mb_strpos(), mb_strrpos(), mb_stripos(), mb_strripos(), mb_strstr(), mb_stristr(), mb_strrchr(), mb_strrichr() 関数の `needle` 引数は、空に出来るようになりました。

- mb_decode_numericentity() 関数で内部的に使われていなかった 引数 `is_hex` は削除されました。

- mb_strrpos() 関数の第三引数に、 オフセットではなくエンコーディングを渡していた古い振る舞いは削除されました。 明示的にオフセットに `0` を渡し、 第四引数にエンコーディングを渡す方法を代わりに使うべきです。

- 文字エンコーディング `ISO_8859-*` のエイリアスは `ISO8859-*` に置き換えられました。 これは、iconv 拡張モジュールと相互運用性を向上させるためです。 アンダースコア付きの mbregex の ISO 8859 aliases (`ISO_8859_*` と `ISO8859_*`) も削除されています。

- mb_ereg() と mb_eregi() 関数は、 マッチに成功した場合に `true` を返すようになりました。 これより前のバージョンでは、 `matches` が渡されなかった場合に 整数 `1` が返されていました。 `matches` が渡された場合には `max(1, strlen($matches[0]))` が返されていました。

### OCI8

- OCI-Lob クラスは OCILob と呼ばれるようになり、 OCI-Collection クラスは OCICollection と呼ばれるようになりました。 これは、PHP 8 の arginfo 型アノテーションツールの 名前に関する規約で強制されたものです。

- いくつかの関数エイリアスが推奨されなくなりました。

- oci_internal_debug() 関数と そのエイリアス ociinternaldebug() は削除されました。

### ODBC

- odbc_connect() 関数は 接続を使い回さなくなりました。

- odbc_exec() 関数で使われていなかった `flags` 引数が削除されました。

### OpenSSL

- openssl_seal() と openssl_open() 関数には `method` を渡すことが必須になりました。 なぜなら、以前のデフォルト値 `"RC4"` はセキュアでないと見なされているからです。

### 正規表現 (Perl互換)

不正なエスケープシーケンスを渡した場合、 もはやリテラルと解釈されなくなりました。 リテラルと解釈する振る舞いは `X` 修正子で必須でしたが、 無視されるようになっています。

### PHP Data Objects(PDO)

- デフォルトのエラーハンドリングのモードが "silent" から "exceptions" に変更されました。 詳細は Errors とエラーハンドリング を参照ください。

- いくつかの PDOクラスのメソッドシグネチャが変更されました:

  - `PDO::query(string $query, ?int $fetchMode = null, mixed ...$fetchModeArgs)`
  - `PDOStatement::setFetchMode(int $mode, mixed ...$args)`

### PDO ODBC

php.ini ディレクティブ pdo_odbc.db2_instance_name は削除されました。

### PDO MySQL

PDO::inTransaction() は、 PDO が管理しているおおよその情報ではなく、 実際のトランザクションの状態を報告するようになりました。 クエリが "暗黙のコミット" に依存していた場合、 PDO::inTransaction() は後に `false` を返します。 なぜなら、トランザクションが既にアクティブではないからです。

### PostgreSQL

- pg_connect() 関数で 推奨されなくなっていた、 接続文字列の代わりに複数の引数を受け入れる文法は もはやサポートされなくなりました。

- 推奨されなくなっていた pg_lo_import() と pg_lo_export() 関数の、 最後の引数で接続を渡すシグネチャはサポートされなくなりました。 代わりに、接続は最初の引数で渡すべきです。

- pg_fetch_all() 関数 は 結果セットの行が0行の場合に、`false` ではなく空の配列を返すようになりました。

### Phar

phar に関連付けられたメタデータは、自動的にアンシリアライズされなくなりました。 これは、オブジェクトのインスタンス化やオートローディングなどに起因する、 潜在的なセキュリティ上の脆弱性を修正するためです。

### リフレクション

- メソッドシグネチャに関する変更

  - `ReflectionClass::newInstance($args)`
  - `ReflectionFunction::invoke($args)`
  - `ReflectionMethod::invoke($object, $args)`

  は、以下のように変更されました:

  - `ReflectionClass::newInstance(...$args)`
  - `ReflectionFunction::invoke(...$args)`
  - `ReflectionMethod::invoke($object, ...$args)`

  PHP 7 と PHP 8 の間で互換性を保たなければならないコードは、 両方のバージョンで互換性を取るために、以下のようなシグネチャが使えます:

  - `ReflectionClass::newInstance($arg = null, ...$args)`
  - `ReflectionFunction::invoke($arg = null, ...$args)`
  - `ReflectionMethod::invoke($object, $arg = null, ...$args)`

- ReflectionType::__toString() メソッドは、 完全な型のデバッグ用の文字列表現を返すようになり、非推奨ではなくなりました。 特に、nullable な型に対しては、nullを代入できることを示す情報が含まれるようになります。 戻り値のフォーマットは安定しておらず、PHP のバージョンによって変わる可能性があります。

- リフレクションの export() メソッドは削除されました。 代わりに、リフレクションオブジェクトを文字列にキャストすることができます。

- ReflectionMethod::isConstructor() と ReflectionMethod::isDestructor() メソッドは インターフェイスの __construct() と __destruct() についても `true` を返すようになりました。 これより前のバージョンでは、クラスとトレイトのメソッドに対してだけ `true` を返していました。

- ReflectionType::isBuiltin() メソッドは、 ReflectionNamedType クラスに移動しました。 ReflectionUnionType クラスには存在しなくなっています。

### Sockets

- 推奨されなくなっていた socket_addrinfo_lookup() 関数の `flags` に指定する `AI_IDN_ALLOW_UNASSIGNED` および `AI_IDN_USE_STD3_ASCII_RULES` は削除されました。

### Standard PHP Library (SPL)

- SplFileObject::fgetss() メソッドは削除されました。

- SplFileObject::seek() は、 常に行の先頭にシークするようになりました。 これより前のバージョンでは、 `>=1` を position に指定すると、次の行の先頭を探していました。

- SplHeap::compare() はメソッドシグネチャを指定するようになりました。 このメソッドを実装する継承先のクラスは、 互換性のあるメソッドシグネチャを持たなければなりません。

- SplDoublyLinkedList::push(), SplDoublyLinkedList::unshift() および SplQueue::enqueue() は、`true` ではなく void を返すようになりました。

- spl_autoload_register() 関数は、 引数が不正な場合には常に TypeError を発生させるようになりました。 よって、2番目の引数 `do_throw` は無視され、 `false` を設定すると、警告が発生します。

- SplFixedArray クラスは Iterator ではなく IteratorAggregate を実装しました。 SplFixedArray::rewind(), SplFixedArray::current(), SplFixedArray::key(), SplFixedArray::next(), SplFixedArray::valid() は削除されました。 代替として、SplFixedArray::getIterator() が追加されました。 SplFixedArray を通じて明示的にイテレーションを行うあらゆるコードは、 SplFixedArray::getIterator() メソッドを使い Iterator を取得しなければなりません。 これは、SplFixedArray がネストされたループ中で安全に使えるようになったということです。

### 標準ライブラリ

- assert() 関数は 文字列の引数を評価しなくなりました。 代わりに、他の引数と同じように扱われます。 `assert('$a == $b')` ではなく `assert($a == $b)` を使うべきです。 INI ディレクティブ assert.quiet_eval と 定数 `ASSERT_QUIET_EVAL` も削除されました。 なぜなら、もはや何の効果も無いからです。

- parse_str() は、 結果の配列を指定しなければ使えなくなりました。

- string.strip_tags フィルタは削除されました。

- strpos(), strrpos(), stripos(), strripos(), strstr(), strchr(), strrchr(), stristr() 関数の `needle` 引数は常に文字列として解釈されるようになりました。 これより前のバージョンでは、 文字列でない引数は ASCII コードポイントと解釈されていました。 chr() 関数を明示的に呼ぶことで、 以前の振る舞いを復元できます。

- strpos(), strrpos(), stripos(), strripos(), strstr(), stristr(), strrchr() 関数の `needle` 引数は、空に出来るようになりました。

- substr(), substr_count(), substr_compare(), iconv_substr() 関数の `length` 引数は `null` も指定できるようになりました。 `null` を指定した場合、 length 引数が指定されなかったことと同じように振る舞います。 よって、この場合、空文字列ではなく、残りの文字列を返します。

- array_splice() 関数の `length` 引数は `null` も指定できるようになりました。 `null` を指定した場合、引数を省略した場合と同じ振る舞いをします。 よって、`offset` から配列の最後までの全ての要素を削除する動きになります。

- vsprintf(), vfprintf(), vprintf() 関数の `args` 引数は、配列であることが必須になりました。 これより前のバージョンでは、あらゆる型の値を受け入れていました。

- password_hash() 関数の `'salt'` オプションはサポートされなくなりました。 `'salt'` オプションを使うと警告が生成され、 指定された salt は無視されます。 そして生成された salt が代わりに使われます。

- quotemeta() 関数は、空文字列を渡すと空文字列を返すようになりました。 これより前のバージョンでは、`false` を返していました。

- 以下の関数は削除されました:

  - hebrevc()
  - convert_cyr_string()
  - money_format()
  - ezmlm_hash()
  - restore_include_path()
  - get_magic_quotes_gpc()
  - get_magic_quotes_runtime()
  - fgetss()

- 定数 `FILTER_SANITIZE_MAGIC_QUOTES` は削除されました。

- `($pieces, $glue)` のような形で、implode() 関数を逆の引数の順番で呼ぶことはサポートされなくなりました。

- parse_url() 関数は、 query および fragment が存在しないことと、空であることを区別するようになりました:

  - `http://example.com/foo → query = null, fragment = null`
  - `http://example.com/foo? → query = "", fragment = null`
  - `http://example.com/foo# → query = null, fragment = ""`
  - `http://example.com/foo?# → query = "", fragment = ""`
  これより前のバージョンでは、上の全ての場合で、query と fragment の値が `null` になっていました。

- var_dump() と debug_zval_dump() 関数は INIディレクティブ precision ではなく serialize_precision を使って浮動小数点を印字するようになりました。 デフォルトの設定では、浮動小数点はこのデバッグ関数によって 全精度で印字されるようになるということです。

- __sleep() が返す 配列に存在しないプロパティが含まれていた場合、 静かに無視されるようになりました。 これより前のバージョンでは、 そうしたプロパティは値 `null` を持つかのようにシリアライズされていました。

- デフォルトの起動時のロケールは、常に `"C"` になりました。 デフォルトでは、どのロケールからも環境を継承しません。 これより前のバージョンでは、 `LC_ALL` は `"C"` に設定されていましたが、 `LC_CTYPE` は環境から情報を継承していました。 しかしながら、関数によっては、明示的に setlocale() を呼び出さないと 継承した環境を尊重しないものもあります。 ロケールをデフォルトから変えるためには、 setlocale() 関数を明示的に呼ぶことが常に必須になりました。

- 非推奨になっていた crypt() 関数が DES にフォールバックする振る舞いが削除されました。 不明な salt フォーマットを crypt() 関数に渡すと、 弱い DES ハッシュにフォールバックするのではなく、 `*0` という値になり、失敗するようになります。

- crypt() 関数に、 SHA256/SHA512 の範囲外の round を指定すると、 最も近い境界値に切り詰めるのではなく、 `*0` という値になり、失敗するようになりました。 これは、glibc の振る舞いと一致します。

- 配列に比較結果が等しい要素が含まれている場合、ソートを行う関数の結果が変わる可能性があります。

- コールバックを受け入れるあらゆる関数のうち、 リファレンスの引数を受け入れるように明示的に指定して「いない」 ものに対し、 リファレンスを使ったコールバックを渡すと警告が発生するようになりました。 例としては、 array_filter() や array_reduce() 関数があります。 これらでほとんどの関数の例を示していますが、全てではありません。

- file_get_contents() 関数のように、 関数が使うHTTPストリームラッパーは、 デフォルトで HTTP/1.0 ではなく、 HTTP/1.1 を指定するようになりました。 これによって、クライアントの振る舞いが変わるわけではありませんが、 サーバーが異なるレスポンスを返す可能性があります。 古い振る舞いをさせるには、 以下のようにして `'protocol_version'` ストリームコンテキストオプションを設定して下さい。

      <?php
      $ctx = stream_context_create(['http' => ['protocol_version' => '1.0']]);
      echo file_get_contents('http://example.org', false, $ctx);
      ?>

- 明示的に salt を指定せず crypt() 関数を呼ぶことはサポートされなくなりました。 自動的に生成される salt で強いハッシュを生成したい場合、 代わりに password_hash() を使って下さい。

- substr(), mb_substr(), iconv_substr(), grapheme_substr() 関数は、 文字列の境界を越えたオフセットを一貫した形で処理するようになりました。 これより前のバージョンでは、空文字列ではなく `false` を返す場合がありました。

- Windows では、 シェルを使い、プログラムを実行する関数 (proc_open(), exec(), popen() など) は、 一貫して %comspec% /s /c "$commandline" を使うようになりました。 これは、(追加のクォート無しで) $commandline を実行することと同じです。

### Sysvsem

- sem_get() 関数の `auto_release` 引数は、 int ではなく bool の値を受け入れるように変更されました。

### Tidy

- 内部的に使われていなかった `use_include_path` 引数が、 tidy_repair_string() 関数から削除されました。

- tidy::repairString(), tidy::repairFile() が、staticメソッドになりました。

### Tokenizer

- `T_COMMENT` トークンは最後の改行文字を含まなくなりました。 改行文字はその後に続く `T_WHITESPACE` トークンに含まれるようになります。 注意すべきなのは、 `T_COMMENT` の後にホワイトスペースが続くとは限らないことです。 `T_CLOSE_TAG` やファイルの終端が続く場合もありえます。

- 名前空間の中にある名前は、 `T_NAME_QUALIFIED` (`Foo\Bar`), `T_NAME_FULLY_QUALIFIED` (`\Foo\Bar`), `T_NAME_RELATIVE` (`namespace\Foo\Bar`) トークンを使って表現されるようになりました。 `T_NS_SEPARATOR` トークンは 単独の名前空間の区切り文字としてだけ使われます。 そして、グループ化されたuse宣言と一緒に使った場合にだけ文法的に合法です。

### XMLReader

XMLReader::open(), XMLReader::XML() が staticメソッドになりました。 これらは、まだインスタンスメソッドとして呼び出すことが出来ますが、 クラスを継承し、これらのメソッドをオーバーライドする場合は、 それらは static として宣言する必要があります。

### XML-RPC

XML-RPC 拡張モジュールは PECL に移動し、PHPの一部として配布されなくなりました。

### Zip

`ZipArchive::OPSYS_Z_CPM` は削除されました(この名前は typo でした)。 `ZipArchive::OPSYS_CPM` を代わりに使って下さい。

### Zlib

- gzgetss() 関数が削除されました。

- zlib.output_compression は、`Content-Type: image/*` を自動的に無効にすることはなくなりました。

### Windows の PHP Test Packs

テストランナーの名前が、run-test.php から run-tests.php に変更されました。 これは、php-src の名前に合わせるためです。

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