【PHP8.4】PHP8.4がリリースされたので新機能全部やる

[PHP8.4](https://qiita.com/rana_kualu/items/9c4d476a4c044bac265f) / [PHP8.3](https://qiita.com/rana_kualu/items/f03efb9810c3ac5b2ab6) / [PHP8.2](https://qiita.com/rana_kualu/items/64bd73ad3d314a1cccdc) / [PHP8.1](https://qiita.com/rana_kualu/items/e350b8ff80f929626eb9)


2024/11/24に[PHP8.4がリリースされました](https://www.php.net/)。
大きな新機能については、PHP8.0以降公開されるようになった[ランディングページ](https://www.php.net/releases/8.4/)で見ることができます。
また[マイグレーションガイド](https://www.php.net/manual/ja/migration84.php)も存在します。

採用されたRFCについては[PHP8.4の新機能](https://qiita.com/rana_kualu/items/b195b1adc60b763843d9)でまとめています。

ここでは、概要だけではなく[UPGRADING](https://github.com/php/php-src/blob/php-8.4.1/UPGRADING)に載っている全ての変更点を全部見て回ることにします。


# Backward Incompatible Changes

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

## Core


### The type of PHP_DEBUG and PHP_ZTS constants changed to bool.

定数[PHP_DEBUGとPHP_ZTS](https://www.php.net/manual/ja/reserved.constants.php)がbool型になりました。
PHP8.3まではint型でした。

### The name of uploaded files and files created by the tempnam() function are now 13 bytes longer

アップロードされたファイル、および[tempnam](https://www.php.net/manual/ja/function.tempnam.php)で作られるファイル名の長さが13バイト長くなりました。
とあるのですが手元で試したら`54bEA6C.tmp`ってかんじで変わってませんでした。
Windowsでは効かないようです。

### Encountering recursion during comparison now results in a Error exception, rather than a fatal error.

比較中に再帰ループに入ったらFatal Errorになっていたのが例外になりました。

```php
1 === hoge();
function hoge(){
    return hoge();
}
```

とあるのですが、↑の例はAllowed memory size exhaustedのFatal Errorになりました。
この使い方ではないということなのか？


### Indirect modification of readonly properties within __clone() is no longer allowed

`__clone()`中にreadonlyプロパティの間接的な書き換えができなくなりました。

PHP8.3で[`__clone()`中にreadonlyプロパティを書き替えできるようになった](https://wiki.php.net/rfc/readonly_amendments)のですが、リファレンスから書き替えできないように制限を入れるようです。

```php
class Foo {
    public function __construct(public readonly DateTime $bar){}

    public function __clone()
    {
        $ref = &$this->bar;
        $ref->modify('+1 year');
    }
}

$foo = new Foo(new DateTime());
$foo2 = clone $foo;
var_dump($foo);
```

と思ったんだけどなんかこれ普通に動きました。
"Indirect modification"ってどういうことなんだろう？


### The exit (and die) language constructs now behave more like a function.

[exit()](https://www.php.net/manual/ja/function.exit.php)は言語構造から[普通の関数になりました](https://qiita.com/rana_kualu/items/60912b8cac8deeaa3560)。

```php
'exit'();

// PHP8.4 エラー出ない
// PHP8.3 Fatal error: Uncaught Error: Call to undefined function exit()
```

これまでの言語構造`exit;`も当面は使用可能です。

### The E_STRICT constant was deprecated and its corresponding error level was removed.

[定数E_STRICT](https://www.php.net/manual/ja/errorfunc.constants.php)は[非推奨](https://wiki.php.net/rfc/deprecations_php_8_4#remove_e_strict_error_level_and_deprecate_e_strict_constant)になりました。
この警告は主にPHP5時代の古い書き方をどうにかするためのものだったのですが、その後E_WARININGや例外に置き換えられてPHP8になったころにはほぼなくなっていたので、役割は終わりました。


## Extension Class constants are now typed

以下エクステンションのクラス定数に型が付きました。
・Date
・Intl
・PDO
・Reflection
・SPL
・Sqlite
・XMLReader

```php
echo new ReflectionClassConstant('PDO', 'PARAM_BOOL')->getType(); // int
```

むしろ型がついていないクラス定数ってあるのか？

## Resource to Object conversions

以下のいくつかの関数が、これまでリソースを返していたのがオブジェクトを返すようになりました。
PHPは8.0あたりから、[リソースを滅ぼすべく動いています](https://wiki.php.net/rfc/resource_to_object_conversion)。

この変更は互換性を重視しており、[is_resource()](https://www.php.net/manual/ja/function.is-resource.php)でのチェックこそ引っかかってしまいますが、それ以外は[そのままで動く](https://qiita.com/rana_kualu/items/b195b1adc60b763843d9#make-the-gmp-class-final)ようになっています。

・[dba_open()](https://www.php.net/manual/ja/function.dba-open.php)と[dba_popen()](https://www.php.net/manual/ja/function.dba-popen.php)
・[odbc_connect](https://www.php.net/manual/ja/function.odbc-connect.php)・[odbc_pconnect](https://www.php.net/manual/ja/function.odbc-pconnect.php)および類似の関数。
・[SoapClient::$httpurlと`SoapClient::$sdl](https://www.php.net/manual/ja/class.soapclient.php)。


## New warnings and exceptions

新たな警告と例外。

### curl_multi_select throws a ValueError if the timeout argument if it's negative or greater than PHP_INT_MAX

[curl_multi_select](https://www.php.net/manual/ja/function.curl-multi-select.php)は引数`$timeout`にマイナス値やPHP_INT_MAX以上を渡されるとValueErrorを出すようになりました。

### imagejpeg/imagewebp/imagepng/imageavif throws an exception if an invalid  quality parameter value is passed.

imagejpeg/imagewebp/imagepng/imageavifは引数として無効な値を渡されたときに例外を出すようになりました。

### imagescale throws an exception if the width/height argument underflows/overflows or

imagescaleは引数として範囲外の値を渡されたときに例外を出すようになりました。

### bind_textdomain_codeset, textdomain and d(*)gettext functions now throw an exception if the domain argument is empty

[bind_textdomain_codeset](https://www.php.net/manual/ja/function.bind-textdomain-codeset.php)は引数`$domain`が空だと例外を出すようになりました。

###  resourcebundle_get(), ResourceBundle::get(), and accessing offsets on a ResourceBundle object now throw

[ResourceBundle::get](https://www.php.net/manual/ja/resourcebundle.get.php)およびResourceBundleオブジェクトは、不正な型にTypeError、不正な値にValueErrorを出すようになりました。

### IntlDateFormatter::__construct() throws a ValueError if the locale is invalid.

[IntlDateFormatter::__construct](https://www.php.net/manual/ja/intldateformatter.create.php)は引数`$locale`が不正な場合に例外を出すようになりました。

### NumberFormatter::__construct() throws a ValueError if the locale is invalid

[NumberFormatter::__construct](https://www.php.net/manual/ja/numberformatter.create.php)は引数`$locale`が不正な場合に例外を出すようになりました。

### mb_encode_numericentity() and mb_decode_numericentity() now check that the $map is only composed of integers

[mb_encode_numericentity](https://www.php.net/manual/ja/function.mb-encode-numericentity.php)・[mb_decode_numericentity](https://www.php.net/manual/ja/function.mb-decode-numericentity.php)の引数`$map`は整数値以外にValueErrorを出すようになりました。

### mb_http_input() now always throws a ValueError if the $type is invalid

[mb_http_input](https://www.php.net/manual/ja/function.mb-http-input.php)は引数`$type`が不正な場合に例外を出すようになりました。

### mb_http_output() now checks that the $encoding parameter does not contain any null bytes

[mb_http_output](https://www.php.net/manual/ja/function.mb-http-output.php)は引数`$encoding`をヌルバイトチェックするようになりました。

### odbc_fetch_row() now emits a warning when a value less than or equal to 0 is passed for parameter $row

[odbc_fetch_row](https://www.php.net/manual/ja/function.odbc-fetch-row.php)は引数`$row`に0以下を渡すと警告を出すようになりました。


### The functions pcntl_sigprocmask(), pcntl_sigwaitinfo() and pcntl_sigtimedwait() now throw

[pcntl_sigprocmask](https://www.php.net/manual/ja/function.pcntl-sigprocmask.php)・[pcntl_sigwaitinfo](https://www.php.net/manual/ja/function.pcntl-sigwaitinfo.php)・[pcntl_sigtimedwait](https://www.php.net/manual/ja/function.pcntl-sigtimedwait.php)は引数`$signals`が不正な場合に例外を出すようになりました。

### Calling simplexml_import_dom() with a non-XML object now throws a TypeError instead of a ValueError

[simplexml_import_dom](https://www.php.net/manual/ja/function.simplexml-import-dom.php)は引数`$node`にDOM以外を渡した場合に、これまでValueErrorを出していたのがTypeErrorを出すようになりました。

### round() now validates the value of the $mode parameter and throws a ValueError for invalid modes

[round](https://www.php.net/manual/ja/function.round.php)は引数`$mode`が不正な場合に、これまではPHP_ROUND_HALF_UPとみなしていたのが例外を出すようになりました。

### The str_getcsv() function now throws ValueErrors 

[str_getcsv](https://www.php.net/manual/ja/function.str-getcsv.php)は引数`$separator`と`$enclosure`が1バイトでない場合に例外を出すようになりました。
これによって動きが[fgetcsv](https://www.php.net/manual/ja/function.fgetcsv.php)と揃いました。

### php_uname() now throws ValueErrors if the $move parameter is invalid

[php_uname](https://www.php.net/manual/ja/function.php-uname.php)は引数`$mode`が不正な場合に例外を出すようになりました。

### The "allowed_classes" option for unserialize() now throws TypeErrors and ValueErrors

[unserialize](https://www.php.net/manual/ja/function.unserialize.php)は引数`$options`のallowed_classesに正しくない値が入ってきたら例外を出すようになりました。

### Passing an invalid character encoding to XMLReader::open() or XMLReader::XML() now throws a ValueError

[XMLReader::open](https://www.php.net/manual/ja/xmlreader.open.php)は引数`$encoding`が不正な場合に例外を出すようになりました。


### XSLTProcessor::setParameter() will now throw a ValueError when its arguments contain null bytes

[XSLTProcessor::setParameter](https://www.php.net/manual/ja/xsltprocessor.setparameter.php)はヌルバイトが入ってきたら例外を出すようになりました。

### Calling XSLTProcessor::importStyleSheet() with a non-XML object now throws a TypeError instead of a ValueError

[XSLTProcessor::importStyleSheet](https://www.php.net/manual/ja/xsltprocessor.importstylesheet.php)は引数`$stylesheet`がXMLオブジェクトでない場合に、これまでValueErrorを出していたのがTypeErrorを出すようになりました。

### Failure to call a PHP function callback during evaluation now throws instead of emitting a warning


[DOMXPath::registerPhpFunctions()](https://www.php.net/manual/ja/domxpath.registerphpfunctions.php)においてコールバック関数の呼び出しに失敗した場合、これまでE_WARNINGを出していたのが[例外になりました](https://wiki.php.net/rfc/improve_callbacks_dom_and_xsl)。


## DOM

### Some DOM methods previously returned false or a PHP_ERR DOMException

[DOM](https://www.php.net/manual/ja/book.dom.php)の幾つかのメソッドで、ノードを追加することに失敗するとこれまでfalseを返していたのがDOMExceptionを出すようになりました。
ただし、実際にこれが発生する可能性は非常に低く、影響はほぼありません。

### Previously, DOMXPath objects could be cloned, but resulted in an unusable object

[DOMXPath](https://www.php.net/manual/ja/class.domxpath.php)をcloneすると例外を出すようになりました。
これまではcloneされたように見えて実際は使用不能なオブジェクトができていました。

### Removed DOMImplementation::getFeature()

[DOMImplementation::getFeature()](https://wiki.php.net/rfc/deprecations_php_8_4#remove_domimplementationgetfeature_feature_version)が削除されました。

## GMP

### The GMP class is now final and cannot be extended anymore

[GMP](https://www.php.net/manual/ja/class.gmp.php)は[finalクラスになり](https://wiki.php.net/rfc/gmp-final)、extendsできなくなりました。

## MBString

### On invalid strings (those with encoding errors), mb_substr() now interprets character indices in the same manner as most other mbstring functions

[mb_substr](https://www.php.net/manual/ja/function.mb-substr.php)は、不正な文字を渡された場合の文字数カウントを[他のmbstring関数](https://www.php.net/manual/ja/ref.mbstring.php)と揃えました。
すなわち、[mb_strpos](https://www.php.net/manual/ja/function.mb-strpos.php)の返り値をそのままmb_substrに渡せます。

### For SJIS-Mac (MacJapanese) strings, character indices passed to mb_substr() now refer to the indices of the Unicode codepoints

`SJIS-Mac`エンコーディングを使っている場合、[mb_substr](https://www.php.net/manual/ja/function.mb-substr.php)等に渡されるインデックスがUnicodeコードポイントのインデックスを参照するようになりました。

とあるんだけどMACじゃないのでよくわからない。


## Mysqli

### The unused and undocumented constant MYSQLI_SET_CHARSET_DIR has been removed

定数MYSQLI_SET_CHARSET_DIRが削除されました。
この定数は使用されておらず、ドキュメント化もされていませんでした。

### The MYSQLI_STMT_ATTR_PREFETCH_ROWS constant has been removed

定数MYSQLI_STMT_ATTR_PREFETCH_ROWSが削除されました。
この定数はmysqlndでは使用できませんでした。

### The MYSQLI_CURSOR_TYPE_FOR_UPDATE and MYSQLI_CURSOR_TYPE_SCROLLABLE constants have been removed

定数MYSQLI_CURSOR_TYPE_FOR_UPDATE・MYSQLI_CURSOR_TYPE_SCROLLABLEが削除されました。
この定数はmysqlndでもlibmysqlでも使用できませんでした。

### The unused MYSQLI_TYPE_INTERVAL constant, which is currently a stub and an alias for MYSQLI_TYPE_ENUM, has been removed

定数MYSQLI_TYPE_INTERVAL・MYSQLI_TYPE_ENUMが削除されました。
MySQLにこれらの型が追加される予定は、いまのところありません。

## MySQLnd

### The error code reported for MySQL server wait timeouts has been changed from 2006 to 4031

MySQLサーバのバージョン8.0.24以降、サーバタイムアウトのエラーコードが`2006`から`4031`に変更になりました。

## Opcache


### The JIT config defaults changed

JITのINI設定値のデフォルトが、`opcache.jit_buffer_size=0`から`opcache.jit_buffer_size=64M / opcache.jit=disable`に変更されました。
これまでjit_buffer_size=0ならJIT無効と判断していたところを、状態を表すフラグで判断するようになり、見た目わかりやすくなりました。


### The maximum value of the opcache.interned_strings_buffer setting on 64bit architectures is now 32767

`opcache.interned_strings_buffer`の最大値が4096から32767になりました。

### If JIT is enabled, PHP will now exit with a fatal error on startup in case of JIT startup initialization issues

JITが有効な場合、JITの初期化に失敗するとPHPが致命的エラーを発生して終了します。


## PCNTL

### The functions pcntl_sigprocmask(), pcntl_sigwaitinfo() and pcntl_sigtimedwait() now always return false on failure

[pcntl_sigprocmask](https://www.php.net/manual/ja/function.pcntl-sigprocmask.php)・[pcntl_sigwaitinfo](https://www.php.net/manual/ja/function.pcntl-sigwaitinfo.php)・[pcntl_sigtimedwait](https://www.php.net/manual/ja/function.pcntl-sigtimedwait.php)は、失敗した場合に必ずfalseを返します。
以前は時折-1を返すことがありました。

## PCRE

### The bundled pcre2lib has been updated to version 10.44

バンドルされているpcre2libがバージョン10.44になりました。
結果、`{,3}`がテキストではなく量指定子になるなど、[一部の正規表現の動作が変更](https://github.com/PCRE2Project/pcre2/blob/master/NEWS)されます。

## PDO_DBLIB

### setAttribute, DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER and DBLIB_ATTR_DATETIME_CONVERT have been changed to set value as a bool

[PDO_DBLIB](https://www.php.net/manual/ja/ref.pdo-dblib.php)のsetAttributeに渡す定数DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIERとDBLIB_ATTR_DATETIME_CONVERTの型がboolになりました。

この定数[ドキュメントに存在しない](https://www.php.net/manual/ja/pdo.setattribute.php)ので詳細不明です。


## PDO_FIREBIRD

### Since some Firebird C++ APIs are used now, this extension requires a C++ compiler to be built

Firebirdは一部でC++ APIが使用されているため、ビルドにはC++コンパイラが必要です。

### getAttribute, ATTR_AUTOCOMMIT has been changed to get the value as a bool

定数PDO::ATTR_AUTOCOMMITは値がintからboolになりました。


## PDO_MYSQL

### getAttribute, ATTR_AUTOCOMMIT, ATTR_EMULATE_PREPARES, MYSQL_ATTR_DIRECT_QUERY have been changed to get values as bool

定数PDO::ATTR_AUTOCOMMIT・PDO::ATTR_EMULATE_PREPARES・PDO::MYSQL_ATTR_DIRECT_QUERYの型がintからboolになりました。

## PDO_PGSQL

### The DSN's credentials, when set, are given priority over their PDO constructor counterparts

DSNの資格情報が、PDOコンストラクタの資格情報よりも優先されるようになります。

## SimpleXML

### Get methods called, or casting to a string on a SimpleXMLElement will no longer implicitly reset the iterator data

get系メソッドを呼んだり、SimpleXMLElementにキャストしたりしても内部ポインタがリセットされなくなりました。
これまでは`foreach()`内でgetName()すると[無限ループ](https://github.com/php/php-src/issues/12192)していましたが、ループしなくなりました。

## SOAP

### SoapClient::$typemap is now an array rather than a resource

[SoapClient::$typemap](https://www.php.net/manual/ja/class.soapclient.php)はリソースから配列になりました。

### The SOAP extension gained an optional dependency on the session extension

SOAPエクステンションはセッションに依存するようになりました。
セッションエクステンションをロードせずにSOAPエクステンションを使うと起動時にエラーになります。

## Standard

### strcspn() with empty $characters now returns the length of the string instead of incorrectly stopping at the first NUL character

[strcspn](https://www.php.net/manual/ja/function.strcspn.php)の引数`$characters`に空文字を渡した場合、これまでヌルバイトで止まっていたのを[文字列長を返す](https://github.com/php/php-src/issues/12592)ようになりました。

### http_build_query() now correctly handles backed enums

[http_build_query](https://www.php.net/manual/ja/function.http-build-query.php)は、[Backed ENUM](https://www.php.net/manual/ja/language.enumerations.backed.php)を正しく処理できるようになりました。

### stream_bucket_make_writeable() and stream_bucket_new() will now return a StreamBucket instance instead of an instance of stdClass

[stream_bucket_make_writeable](https://www.php.net/manual/ja/function.stream-bucket-make-writeable.php)・[stream_bucket_new](https://www.php.net/manual/ja/function.stream-bucket-new.php)は、これまでstdClassを返していたのを[StreamBucketを返す](https://wiki.php.net/rfc/dedicated_stream_bucket)ようになりました。

## Tidy

### Failures in the constructor now throw exceptions rather than emitting warnings and having a broken object

Tidyコンストラクタで問題が起きた場合、今までは壊れたオブジェクトが返っていたのが例外が出るようになりました。


# New Features

新機能。

## Core

### Added request_parse_body() function

関数[request_parse_body](https://qiita.com/rana_kualu/items/8a95669ebbfd19e27da9)が追加されました。
POST以外のHTTPメソッドではリクエストボディを取得するのが何気に面倒だったのですが、関数ひとつで取得できるようになります。

```php
// REST ClientでPUTを送る
PUT https://test.localhost/sample.php HTTP/1.1
Content-Type: application/json

{
    "foo": "bar",
    "hoge": "fuga"
}

// PHPで取得
var_dump($_REQUEST); // [] 取れない
[$body, $files] = request_parse_body(); // [foo=>bar, hoge=>fuga]
```

むしろ今まで困難だったことに驚きですね。

### Getting the debug info for WeakReference will now also output the object it references

[WeakReference](https://www.php.net/manual/ja/class.weakreference.php)のデバッグ情報に、参照先も出力されるようになりました。

```php
$obj = new stdClass;
$weakref = WeakReference::create($obj);
var_dump($weakref);

// PHP8.4 object(WeakReference){ object=> object(stdClass)}
// PHP8.3 object(WeakReference){}
```

デバッグが楽になります。

### The output of Closure::__debugInfo() now includes the name, file, and line of the Closure

`Closure::__debugInfo()`のデバッグ情報に、name・file・lineが出力されるようになりました。

```php
$func = static function() { return 1; };
$closure = Closure::bind($func, null);
var_dump($closure);

// PHP8.4 object(Closure){ name=> path/to/name, file=>path/to/file, line=>2 }
// PHP8.3 object(Closure){}
```

デバッグが楽になります。

### new expressions with constructor arguments are now dereferencable

コンストラクタにかぎって、[全体を括弧で囲まなくてもメソッドを連鎖させる](https://qiita.com/rana_kualu/items/5f34ced66558a4f94a4b)ことができるようになりました。

```php
new HOGE()->run();   // PHP8.4以降OK
(new HOGE())->run(); // PHP8.3まで
```

たった2文字の差ですが、躓かず書けるようになるので便利ですね。

### Added the #[\Deprecated] attribute

[Deprecatedアトリビュートが追加](https://qiita.com/rana_kualu/items/a1b420834725f9ff3fc3)されました。

```php
#[\Deprecated]
function test() {}

test();
// PHP8.4 E_USER_DEPRECATED
// PHP8.3 何も起きない
```

廃止したい関数・メソッド・クラス定数を楽に明記できるようになります。
PHP8.3以前ではただのコメントなので、古いバージョンでもそのまま動きます。

### Implemented property hooks

[プロパティフック](https://qiita.com/rana_kualu/items/06d68549058966a34c2b)が追加されました。

```php
<?php
class HOGE{
	public string $tel{
		set{
			$this->tel = $value;
		}
		get => '電話番号は' . $this->tel;
	}
}

$hoge = new HOGE();
$hoge->tel = "0120444444";
echo $hoge->tel; // "電話番号は0120444444"
```

プロパティにsetter/getterを直接記述できる便利機能で、無駄なsetter/getterを排除できます。
文法は[Kotlinのそれ](https://kotlinlang.org/docs/properties.html#getters-and-setters)とだいたい同じです。


### Exiting a namespace now clears seen symbols

名前空間を抜けた際にシンボルもクリアされるようになりました。

ということらしいのですがよくわかりません。
[テストケース](https://github.com/php/php-src/blob/php-8.4.0RC4/Zend/tests/use_function/ns_end_resets_seen_symbols_1.phpt)を見ても何のことだかさっぱりだぜ。

### Implemented asymmetric property visibility.

[非対称可視性](https://qiita.com/rana_kualu/items/c19e8efeb7561165fa64)が導入されました。

```php
class Foo{
    public private(set) string $bar = 'baz';
}

$foo = new Foo();

echo $foo->bar;    // OK
$foo->bar = 'qux'; // エラー
```

`Foo::$bar`は書き込みに対してprivate、読み込みに対してpublicです。
プロパティをprivateにする最大の理由、『見られてもいいけど書き込みはされたくない』をいちいちsetterなどを使わず効率的に表現することができます。

### Implemented lazy objects.

[オブジェクトの遅延初期化](https://wiki.php.net/rfc/lazy-objects)が導入されました。

```php
class MyClass{
    public function __construct(private int $foo){
        // 重い処理
    }
}

$initializer = static function (MyClass $ghost): void {
    $ghost->__construct(123);
};
$reflector = new ReflectionClass(MyClass::class);
// $objectが遅延初期化オブジェクト
$object = $reflector->newLazyGhost($initializer);
```

インスタンス生成は比較的重い処理なので、できればやりたくないしなるべく後回しにしたいという要件に答えます。
ただ使い方がややこしいのと、一般的にはそこまでする理由はあんまりないので、気が付いたら実はフレームワークが裏側で使っていたみたいな用途になるでしょう。

## Curl

### curl_version() returns an additional feature_list value

[curl_version](https://www.php.net/manual/ja/function.curl-version.php)の帰り値にfeature_listが追加されました。
SSLやIPv6など各種プロトコルに対応しているかをboolの連想配列で返します。

### Added CURL_HTTP_VERSION_3 and CURL_HTTP_VERSION_3ONLY constants

CURLOPT_HTTP_VERSIONに渡せる値として定数CURL_HTTP_VERSION_3・CURL_HTTP_VERSION_3ONLYが追加されました。

###  Added CURLOPT_PREREQFUNCTION as a Curl option

接続の確立後、リクエストを送信するまでの間に渡せるオプションCURLOPT_PREREQFUNCTIONが追加されました。
リクエストを送信するか否かを決めるコールバックを渡せるみたい。

### Added CURLOPT_SERVER_RESPONSE_TIMEOUT

定数CURLOPT_SERVER_RESPONSE_TIMEOUTが追加されました。
中身はCURLOPT_FTP_RESPONSE_TIMEOUTと同じです。

### Added CURLOPT_DEBUGFUNCTION support

定数CURLOPT_DEBUGFUNCTIONが追加されました。
コールバックを渡すことでcurl標準のデバッグ関数を置き替えられるみたい。

### curl_getinfo() function now returns "posttransfer_time_us"

[curl_getinfo](https://www.php.net/manual/ja/function.curl-getinfo.php)の返り値にposttransfer_time_usが追加されました。
リクエストの開始から終了までの時間を計ってくれるみたい。
リダイレクトは時間が足されていきます。

## DOM

### Added DOMNode::compareDocumentPosition()

メソッド[DOMNode::compareDocumentPosition()](https://www.php.net/manual/ja/domnode.comparedocumentposition.php)が追加されました。
ふたつのノードがどちらが先にあるのかを調べます。

これ昔からシグネチャはあったものの中身が実装されてなかったからPHP8.0で削除されて、その後PHP8.4で実装されなおしたという愉快な経緯を辿ったようです。

### Added constant

以下の定数が追加されました。

・DOMNode::DOCUMENT_POSITION_DISCONNECTED
・DOMNode::DOCUMENT_POSITION_PRECEDING
・DOMNode::DOCUMENT_POSITION_FOLLOWING
・DOMNode::DOCUMENT_POSITION_CONTAINS
・DOMNode::DOCUMENT_POSITION_CONTAINED_BY
・DOMNode::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC

いずれもDOMの定数をそのまま取り入れただけのようです。

### It is now possible to pass any callable to registerPhpFunctions()

[DOMXPath::registerPhpFunctions](https://www.php.net/manual/ja/domxpath.registerphpfunctions.php)に[任意のcallableを渡せる](https://wiki.php.net/rfc/improve_callbacks_dom_and_xsl)ようになります。

## FPM

### Flushing headers without a body will now succeed

ボディが空でも[flush](https://www.php.net/manual/ja/function.flush.php)が成功するようになりました。

とあるんだけど[プルリクエストの会話](https://github.com/php/php-src/pull/12785)を見てもいまいちわからない。
PHPからパケットを2回送ったのにnginxがコンテンツをブラウザに送信するのは一回だけだった。ならPHPからも一回にまとめて送ればいい、みたいなかんじだろうか？

### Status page has a new field to display a memory peak

[FPMの情報ページ](https://www.php.net/manual/ja/fpm.status.php)に表示される情報にメモリピークが追加されました。

## Intl

### NumberFormatter::ROUND_HALFODD added

定数NumberFormatter::ROUND_HALFODDが追加されました。
既存の[NumberFormatter::ROUND_HALFEVEN](https://www.php.net/manual/ja/class.numberformatter.php)に対する補完です。


## OpenSSL

### Added support for Curve25519 + Curve448 based keys

[openssl_pkey_new](https://www.php.net/manual/ja/function.openssl-pkey-new.php)などが、[Curve25519](https://ja.wikipedia.org/wiki/Curve25519)と[Curve448](https://ja.wikipedia.org/wiki/Curve448)に対応しました。

### Implement PASSWORD_ARGON2 password hashing

[password_hash](https://www.php.net/manual/ja/function.password-hash.php)がPASSWORD_ARGON2に対応しました。

[OpenSSLが対応した](https://docs.openssl.org/master/man7/EVP_KDF-ARGON2/)ので[追随した](https://github.com/php/php-src/issues/13514)ということですが、[PASSWORD_ARGON2I](https://wiki.php.net/rfc/argon2_password_hash)とどう違うのかはよくわかりません。


## PCRE

### The bundled pcre2lib has been updated to version 10.44

同梱のpcre2libが[バージョン10.44](https://github.com/PCRE2Project/pcre2/releases/tag/pcre2-10.44)になりました。
結果、LoongArch JITサポート、可変長の後読みアサーションなどが[サポートされました](https://github.com/PCRE2Project/pcre2/blob/master/ChangeLog)。
名前付きキャプチャグループの最大長が32から128になりました。

### Added support for the "r" (PCRE2_EXTRA_CASELESS_RESTRICT) modifier

修飾子`r`が追加されました。
`i`といっしょに使うと、ASCII文字と非ASCII文字の混在をlock outします。

```php
preg_match('|aK|i', 'aK', $matches); // $matches = []
```

`r`以前に`i`の時点で[同じだと認識しない](https://www.pcre.org/current/doc/html/pcre2unicode.html)んだけどなんでだ？


## PDO

### Added support for driver-specific subclasses

PDOで[データベースごとのサブクラスが実装され](https://qiita.com/rana_kualu/items/6a9d82c8764476839b23)、データベース固有機能が使えるようになります。

```php
// MySQL固有機能が使える
$pdo = new PdoMySql('mysql:host=localhost;dbname=test');
$pdo->getWarningCount();

// PostgreSQL固有機能が使える
$pdo = new PdoPgsql('pgsql:host=localhost;dbname=test');
$pdo->escapeIdentifier($name);

// これまでどおり
$pdo = new PDO('mysql:host=localhost;dbname=test');
```

固有機能を使う必要がない場合は、`new PDO()`のままにしておけばこれまでどおりの動きのままになります。


### Added support for driver specific SQL parsers

SQLのパーサも[データベースごとに対応](https://wiki.php.net/rfc/pdo_driver_specific_parsers)します。

```sql
SELECT '\'', ?'
```

このSQLはMySQLでは正しく動きますが、PostgreSQLでは正しく動きませんでした。
ということでMySQLにはMySQL用のパーサ、PostgreSQLにはPostgreSQL用のパーサを用意します。

## Phar

### Added support for the unix timestamp extension for zip archives

ZipアーカイブにUNIXタイムスタンプ拡張のサポートを追加しました。

とありますがWindowsなのでよくわかりません。

## Readfile

### Added ability to change .php_history path through PHP_HISTFILE env variable

[対話シェルの履歴を保存しているファイル](https://www.php.net/manual/ja/features.commandline.interactive.php)のファイルパスを変更する環境変数PHP_HISTFILEが追加されました。

## Reflection

### ReflectionAttribute now contains a $name property

[ReflectionAttribute](https://www.php.net/manual/ja/class.reflectionattribute.php)に`$name`プロパティが追加されました。


### ReflectionClassConstant::__toString() and ReflectionProperty::__toString() now returns the attached doc comments

[ReflectionClassConstant::__toString()](https://www.php.net/manual/ja/reflectionclassconstant.tostring.php)と[ReflectionProperty::__toString()](https://www.php.net/manual/ja/reflectionproperty.tostring.php)の出力に、Docコメントが追加されました。

```php
class Hoge{
    /**
     * @var string なんか
     * @static
     */
    public const FUGA = 1;
}

$p = new ReflectionClassConstant('Hoge', 'FUGA');
echo $p;


// PHP8.3
Constant [ public int FUGA ] { 1 }

// PHP8.4
﻿/**
  * @var     string なんか
  * @static
 */
Constant [ public int FUGA ] { 1 }
```

これはいったいなんの意味が…

なお、PHPDocコメントを普通に値として取ってきたい場合は[getDocComment()](https://www.php.net/manual/ja/reflectionclassconstant.getdoccomment.php)メソッドがあります。

### Multiple methods and constants related to lazy objects were introduce

[遅延初期化](https://wiki.php.net/rfc/lazy-objects)をリフレクションで取り扱うための各種メソッド・定数が追加されました。

・ReflectionClass::newLazyGhost()
・ReflectionClass::newLazyProxy()
・ReflectionClass::resetAsLazyGhost()
・ReflectionClass::resetAsLazyProxy()
・ReflectionClass::isUninitializedLazyObject()
・ReflectionClass::initializeLazyObject()
・ReflectionClass::markLazyObjectAsInitialized()
・ReflectionClass::getLazyInitializer()
・ReflectionProperty::skipLazyInitialization()
・ReflectionProperty::setRawValueWithoutLazyInitialization()
・ReflectionClass::SKIP_INITIALIZATION_ON_SERIALIZE
・ReflectionClass::SKIP_DESTRUCTOR


## SOAP

### Added support for clark notation for namespaces in class map

クラスマップをClark記法に対応しました。

ということらしいのですが公的情報が全く見当たりません。
どうもXMLの仕様を作った[James Clark](https://en.wikipedia.org/wiki/James_Clark_(programmer))が[非公式に使っていた短縮記法](https://stackoverflow.com/questions/13271370/)みたい。


### Instances of DateTimeInterface that are passed to xsd:datetime or similar elements are now serialized as such

DateTimeInterfaceを`xsd:datetime`に渡した場合、これまでは空文字にされていたのが適切な文字列にシリアライズされるようになりました。


### Session persistence now works with a shared session module

[持続的セッションが共有セッションモジュールで動作するようになりました](https://www.php.net/manual/ja/migration84.new-features.php#migration84.new-features.soap)とあるのですが、正直何言ってるのかわからない。
まず共有セッションモジュールってなんやねん。
まあともかく、一部の特殊なサーバでも[SoapServer::setPersistence](https://www.php.net/manual/ja/soapserver.setpersistence.php)が効くようになったってことでいいんですかね。


## Standard

### Added a new RoundingMode enum with clearer naming and improved discoverability

新しいENUM、[RoundingMode](https://www.php.net/manual/ja/enum.roundingmode.php)が追加されました。

PHP8.4で[round](https://www.php.net/manual/ja/function.round.php)関数の[丸めモードが増えて8つになった](https://qiita.com/rana_kualu/items/b8d8709ecbea06ab1f4d)のですが、定数を増やすのはつらいということで[RoundingModeにまとめる](https://wiki.php.net/rfc/correctly_name_the_rounding_mode_and_make_it_an_enum)ことになりました。
既存の定数が削除される予定はいまのところありません。

```php
round(1.5, 1, PHP_ROUND_HALF_UP);
round(1.5, 1, \RoundingMode::HalfAwayFromZero); // PHP_ROUND_HALF_UPと同じ

round(1.5, 1, \RoundingMode::PositiveInfinity); // 切り上げ
round(1.5, 1, \RoundingMode::NegativeInfinity); // 切り捨て
```


## XSL

### It is now possible to use parameters that contain both single and double quotes

シングルクォートとダブルクォートを両方含んだ文字列を扱えるようになりました。

実は[これまでできませんでした](https://bugs.php.net/bug.php?id=64137)。

### It is now possible to pass any callable to registerPhpFunctions()

[DOMXPath::registerPhpFunctions()](https://www.php.net/manual/ja/domxpath.registerphpfunctions.php)の引数に[callableを渡せるようになりました](https://wiki.php.net/rfc/improve_callbacks_dom_and_xsl)。

```php
$xpath->registerPhpFunctions("callable"); // PHP8.3
$xpath->registerPhpFunctions(["function_name" => $callable]); // PHP8.4
```

これまでは関数名の文字列しか渡すことができませんでした。


### Added XSLTProcessor::$maxTemplateDepth and XSLTProcessor::$maxTemplateVars

[XSLTProcessor](https://www.php.net/manual/ja/class.xsltprocessor.php)にプロパティ`$maxTemplateDepth`・`$maxTemplateVars`が追加されました。
詳細はよくわかりませんがまあ名前のとおりドキュメントの広さを制限することができるパラメータでしょう。

## Zip

### Added ZipArchive::ER_TRUNCATED_ZIP added in libzip 1.11

定数`ZipArchive::ER_TRUNCATED_ZIP`が追加されました。
これは[libzip 1.11](https://libzip.org/news/release-1.11.html)で追加されたエラーコードです。


# Changes in SAPI modules

SAPIの変更。

## apache2handler

### Support for EOL Apache 2.0 and 2.2 has been removed

EOLになっているApache 2.0と2.2のサポートが削除されました。
PHP8.4が対応しているApacheの最低バージョンは2.4です。

## CLI

### The behavior has been changed to look for an index file in all cases

ビルトインサーバは、指定されたファイルが見つからないときに親ディレクトリに遡って探しています。
しかし、ファイル名に`.`が含まれていた場合は遡らないようになっていました。
PHP8.4では、ファイル名に`.`が含まれていた場合でもディレクトリを遡ってファイルを探すようになりました。

## FPM

### /dev/poll events.mechanism setting for Solaris/Illumos had been retired

Solaris用に存在していた`events.mechanism`というイベントメカニズムは削除されました。

Solarisなんて使ったことないからなんのことかわかりません。

# Deprecated Functionality

非推奨になる機能。
基本的にPHP8.4でE_DEPRECATEDとなり、PHP9.0で削除されます。
この機能・書き方は今後使ってはいけません。

## Core

### Implicitly nullable parameter types are now deprecated

[引数のデフォルトNULLが禁止](https://qiita.com/rana_kualu/items/07f829ff763c6a24dd92)されます。

```php
function foo(int $x = null) {
    // Deprecated
}
```

引数の型はintなのに引数を渡さないことが可能なので、型is何？ってなります。

これは[Nullableが導入されたのがPHP7.1](https://wiki.php.net/rfc/nullable_types)だったので、それ以前と互換性を保つためにあえて許されていた構文です。
しかしいいかげんもういいだろうということで禁止となり、今後は正しく`function foo(?int $x)`とする必要があります。

### Passing E_USER_ERROR to trigger_error() is now deprecated

[trigger_error()](http://www.php.net/trigger_error)で[E_USER_ERROR](https://www.php.net/manual/ja/errorfunc.constants.php#constant.e-user-error)を出すことを禁止します。
これはPHP本体が出すE_ERRORと同ランクの致命的なエラーであり、デストラクタやfinallyもパスして実行が即座に中断されます。
適切な回復メカニズムを実行できないのはよろしくないということで、今後は普通にExceptionを使ってくれということになりました。

### Using "_" as a class name is now deprecated

クラス名`_`が禁止されます。

```php
class _ {} // Deprecated
```

むしろ今まで作れてたんかよ。

今後[パターンマッチング](https://wiki.php.net/rfc/pattern-matching)の導入が予定されており、そのために必要となるので布石を打っておくという面もあるようです。

### Raising zero to the power of negative number is deprecated

[ゼロのマイナス累乗が禁止](https://wiki.php.net/rfc/raising_zero_to_power_of_negative_number)されます。

```php
var_dump(0 ** -1);

// PHP8.3 float(INF)
// PHP8.4 float(INF) Deprecated
// PHP9.0 DivisionByZeroError
```

そもそも数学的にはどうなるのが正しいのだろう。

### The E_STRICT constant was deprecated

E_STRICTがなくなりました。

これは元々PHP5時代に不適切なコーディングを防ぐために導入されたものですが、PHP7から8にかけてE_WARNINGなどに振り分けられました。
PHP本体のE_STRICTは[2019年に消滅した](https://github.com/php/php-src/pull/4401)ため、E_STRICT定数も機能も削除します。


## Curl

### The CURLOPT_BINARYTRANSFER constant is deprecated

定数CURLOPT_BINARYTRANSFERが削除されました。

これ、なんと[PHP5.1.3で不要となった](https://www.php.net/ChangeLog-5.php#5.1.3)ものであり、定数だけが今まで残っていました。

## Date

### Calling DatePeriod::__construct(string $isostr, int $options = 0) is deprecated

[DatePeriod::__construct()](https://www.php.net/manual/ja/dateperiod.construct.php)にstringを渡す方法が削除されました。
かわりにDateTimeInterfaceを渡すか、[DatePeriod::createFromISO8601String()](https://www.php.net/manual/ja/dateperiod.createfromiso8601string.php)を使いましょう。

### Constants SUNFUNCS_RET_TIMESTAMP, SUNFUNCS_RET_STRING, and SUNFUNCS_RET_DOUBLE are now deprecated

定数`SUNFUNCS_RET_TIMESTAMP`・`SUNFUNCS_RET_STRING`・`SUNFUNCS_RET_DOUBLE`が削除されました。

そもそもこの定数を使っている関数[date_sunrise()](https://www.php.net/manual/ja/function.date-sunrise.php)が[非推奨になった](https://qiita.com/rana_kualu/items/c894b2160d1f8799eed2#date_sunrise-and-date_sunset)ためです。

## DBA

### Passing null or false to dba_key_split() is deprecated

[dba_key_split](https://www.php.net/manual/ja/function.dba-key-split.php)の引数null・falseが削除されました。
実体のある文字列を渡す必要があります。


## DOM

### Deprecated DOM_PHP_ERR constant

定数DOM_PHP_ERRが[削除されました](https://wiki.php.net/rfc/deprecations_php_8_4#deprecate_dom_php_err_constant)。

[DOMの仕様にない](https://www.php.net/manual/ja/dom.constants.php#constant.dom-php-err)非標準のエラーコードです。

### DOMEntity::$encoding, DOMEntity::$version have been deprecated

[DOMEntity::$encoding](https://www.php.net/manual/ja/class.domentity.php#domentity.props.encoding)など幾つかのプロパティが[削除されました](https://wiki.php.net/rfc/deprecations_php_8_4#formally_deprecate_soft-deprecated_domdocument_and_domentity_properties)。

これらは[少なくとも17年にわたって非推奨](https://github.com/php/doc-en/commit/7fde5c7d758f8c2809fec99ce36b05043847224a)でした。


## Hash

### Deprecated passing incorrect data types for options to ext/hash functions

一部の[ハッシュ関数](https://www.php.net/manual/ja/function.hash-init.php)は、追加のオプションを配列で渡すことができます。
たとえばハッシュアルゴリズム`murmur`は`seed`、`xxh3`は`secret`を受け取ります。

しかし、seedにint型以外を渡したり、secretにstring型以外を渡したりすると、[何ひとつエラーを吐かずに無視](https://github.com/php/php-src/issues/10305)します。

わかりにくいので、正しくない型を渡した場合にValueErrorを出すようにします。

## Intl

### Calling intlcal_set() as well as calling IntlCalendar::set() with more than 2 arguments is deprecated

[IntlCalendar::set()](https://www.php.net/manual/ja/intlcalendar.set.php)に大量の引数を渡す方のシグネチャが削除されました。
一括設定したい場合は[IntlCalendar::setDateTime()](https://www.php.net/manual/ja/intlcalendar.setdatetime.php)を使いましょう。


### Calling intlgregcal_create_instance() as well as calling IntlGregorianCalendar::__construct() with more than 2 arguments is deprecated

[IntlGregorianCalendar::__construct()](https://www.php.net/manual/ja/intlgregoriancalendar.construct.php)に大量の引数を渡す方のシグネチャが削除されました。
一括設定したい場合は[IntlCalendar::createFromDateTime()](https://www.php.net/manual/ja/intlgregoriancalendar.createfromdatetime.php)を使いましょう。


## LDAP

### Calling ldap_connect() with more than 2 arguments is deprecated

[ldap_connect](https://www.php.net/manual/ja/function.ldap-connect.php)に大量の引数を渡す方のシグネチャが削除されました。
一括設定したい場合は[ldap_connect_wallet](https://www.php.net/manual/ja/function.ldap-connect-wallet.php)を使いましょう。

### Calling ldap_exop() with more than 4 arguments is deprecated

[ldap_exop](https://www.php.net/manual/ja/function.ldap-exop.php)に大量の引数を渡す方のシグネチャが削除されました。
一括設定したい場合は[ldap_exop_sync](https://www.php.net/manual/ja/function.ldap-exop-sync.php)を使いましょう。

## Mysqli

### The mysqli_ping() function and mysqli::ping() method are now deprecated

[mysqli_ping](https://www.php.net/manual/ja/mysqli.ping.php)は[削除されました](https://wiki.php.net/rfc/deprecations_php_8_4#mysqli_ping_and_mysqliping)。

これは設定[mysqli.reconnect](https://www.php.net/manual/ja/mysqli.configuration.php#ini.mysqli.reconnect)が有効であれば自動再接続しに行くという機能なのですが、`mysqli.reconnect`自体が[PHP8.2で削除](https://qiita.com/rana_kualu/items/64bd73ad3d314a1cccdc#the-reconnect-property-of-mysqli_driver-has-been-removed)されています。

### The mysqli_kill() function and mysqli::kill() method are now deprecated

[mysqli_kill](https://www.php.net/manual/ja/mysqli.kill.php)は[削除されました](https://wiki.php.net/rfc/deprecations_php_8_4#deprecate_mysqli_kill)。

これはMySQLの[COM_PROCESS_KILL](https://dev.mysql.com/doc/dev/mysql-server/8.0.39/page_protocol_com_process_kill.html)のラッパーなのですが、COM_PROCESS_KILLがMySQL5.7で非推奨になったためです。

### The mysqli_refresh() function and mysqli::refresh() method are now deprecated

[mysqli_refresh](https://www.php.net/manual/ja/mysqli.refresh.php)は[削除されました](https://wiki.php.net/rfc/deprecations_php_8_4#deprecate_mysqli_refresh)。

こちらもMySQL側で[COM_REFRESH](https://dev.mysql.com/doc/dev/mysql-server/8.0.39/page_protocol_com_refresh.html)が非推奨になったためです。

### Passing explicitly the $mode parameter to mysqli_store_result() has been deprecated

[mysqli_store_result](https://www.php.net/manual/ja/mysqli.store-result.php)の第二引数`$result`は[削除されました](https://wiki.php.net/rfc/deprecations_php_8_4#deprecate_the_second_parameter_to_mysqli_store_result)。

この引数は[PHP8.1で無効化されました](https://qiita.com/rana_kualu/items/e350b8ff80f929626eb9#the-mysqli_store_result_copy_data-option-no-longer-has-an-effect)。
今までは指定しても何も起きませんが、PHP8.4ではE_DEPRECATDを出します。

## PDO_PGSQL

### Using escaped question marks (??) inside dollar-quoted strings is deprecated

ドルマークで囲まれた文字列内では`?`のエスケープ`??`が不要になりました。

Postgresは全然使わないので[よくわからない](https://www.postgresql.jp/docs/9.5/sql-syntax-lexical.html#sql-syntax-dollar-quoting)のですが、特定の書式において?プレースホルダを使う場合、これまでは`??`にしないといけなかったのがしなくてよくなったということのようです。
[ドライバごとに個々のSQLのパーサを用意した](https://wiki.php.net/rfc/pdo_driver_specific_parsers)結果です。

## PgSQL

### Calling pg_fetch_result() with 2 arguments is deprecated

[pg_fetch_result](https://www.php.net/manual/ja/function.pg-fetch-result.php)に2引数を渡す方のシグネチャが削除されました。
3引数のほうを使うようにしましょう。

### Calling pg_field_prtlen() with 2 arguments is deprecated

[pg_field_prtlen](https://www.php.net/manual/ja/function.pg-field-prtlen.php)に2引数を渡す方のシグネチャが削除されました。
3引数のほうを使うようにしましょう。

### Calling pg_field_is_null() with 2 arguments is deprecated

[pg_field_is_null](https://www.php.net/manual/ja/function.pg-field-is-null.php)に2引数を渡す方のシグネチャが削除されました。
3引数のほうを使うようにしましょう。


## Random

### lcg_value() is deprecated, as the function is broken in multiple ways.

[lcg_value](https://www.php.net/manual/ja/function.lcg-value.php)が削除されました。
この関数は暗号学的にセキュアではなく、返り値に偏りがあるなど、質のよくない乱数生成器です。

[Random\Randomizer::getFloat](https://www.php.net/manual/ja/random-randomizer.getfloat.php)が上位互換なのでこちらを使いましょう。

## Reflection

### Calling ReflectionMethod::__construct() with 1 argument is deprecated


[pg_field_is_null](https://www.php.net/manual/ja/reflectionmethod.construct.php)に1引数を渡す方のシグネチャが削除されました。
2引数のほう、もしくは[ReflectionMethod::createFromMethodName](https://www.php.net/manual/ja/reflectionmethod.createfrommethodname.php)を使うようにしましょう。

## Session

### Calling session_set_save_handler() with more than 2 arguments is deprecated

[session_set_save_handler](https://www.php.net/manual/ja/function.session-set-save-handler.php)に[たくさんの引数を渡す](https://qiita.com/hnw/items/a0647c6362f2ee3340cb)方のシグネチャが削除されました。
[2引数](https://qiita.com/rana_kualu/items/45afbb591eb8195d2518)のほうを使うようにしましょう。

###  Changing the INI settings session.sid_length and session.sid_bits_per_character is deprecated

INI設定[session.sid_lengthとsession.sid_bits_per_character](https://www.php.net/manual/ja/session.configuration.php)が[削除されました](https://wiki.php.net/rfc/deprecations_php_8_4#sessionsid_length_and_sessionsid_bits_per_character)。

これはセッションIDの長さや文字種を変更できるというパラメータですが、設定によっては[WAFがエラーを出す](https://github.com/php/php-src/issues/12418)ことがわかりました。
そもそもセッションIDの暗号強度をユーザが調整する必要性そのものが皆無であり、常に安全性高めのセッションIDにしておけばいいだろうということで、設定値を変更することが不可能になります。

### Changing the INI settings session.use_only_cookies, session.use_trans_sid, session.trans_sid_tags, session.trans_sid_hosts, and session.referer_check is deprecated

INI設定[session.use_only_cookies](https://www.php.net/manual/ja/session.configuration.php)などいくつかの設定が[削除されました](https://wiki.php.net/rfc/deprecate-get-post-sessions)。

これは[セッションIDをURLに埋め込んでいた超古代文明の遺物](https://qiita.com/rana_kualu/items/4118511b430fff0135d1)であり、現代には全く不要であるため削除されます。


## SOAP

###  The SOAP_FUNCTIONS_ALL constant is now deprecated

定数[SOAP_FUNCTIONS_ALL](https://www.php.net/manual/ja/soap.constants.php#constant.soap-functions-all)は[削除されました](https://wiki.php.net/rfc/deprecations_php_8_4#deprecate_soap_functions_all_constant_and_passing_it_to_soapserveraddfunction)。

これはSOAPサーバで全てのPHP関数を使用可能にするという設定であり、潜在的な脆弱性が存在するため削除されます。

### Passing an int to SoapServer::addFunction() is now deprecated

[SoapServer::addFunction](https://www.php.net/manual/ja/soapserver.addfunction.php)の引数にintを渡すシグネチャは[削除されました](https://wiki.php.net/rfc/deprecations_php_8_4#deprecate_soap_functions_all_constant_and_passing_it_to_soapserveraddfunction)。

intを受け入れる唯一の引数がSOAP_FUNCTIONS_ALLだったため、SOAP_FUNCTIONS_ALLといっしょに削除されます。

## SPL

### The SplFixedArray::__wakeup() method has been deprecated


[SplFixedArray::__wakeup()](https://www.php.net/manual/ja/splfixedarray.wakeup.php)は削除されました。

かわりに[__serialize()](https://www.php.net/manual/ja/splfixedarray.serialize.php)・[__unserialize()](https://www.php.net/manual/ja/splfixedarray.unserialize.php)を使いましょう。

###  Using the default value for $escape parameter is now deprecated


[SplFileObject::setCsvControl()](https://www.php.net/manual/ja/splfileobject.setcsvcontrol.php)・[SplFileObject::fputcsv()](https://www.php.net/manual/ja/splfileobject.fputcsv.php)・[SplFileObject::fgetcsv()](https://www.php.net/manual/ja/splfileobject.fgetcsv.php)の引数`$escape`は[必須になりました](https://wiki.php.net/rfc/deprecations_php_8_4#deprecate_proprietary_csv_escaping_mechanism)。

[fputcsv](https://www.php.net/manual/ja/function.fputcsv.php)など昔からPHPにあるCSV関数は引数`$escape`を持っているのですが、[これを下手に変更するとバグる](https://bugs.php.net/bug.php?id=74713)ことが知られています。
元々CSVフォーマットにエスケープの標準化がなかったせいで起きている混乱なのですが、現在ではほぼ`"`が使われているので、最終的にそれに合わせる目的のようです。
でもそのために必須にするという解決策は正直よくわからない。

```php
fgetcsv($fp, length:null); // E_DEPRECATED the $escape parameter must be provided as its default value will change
fgetcsv($fp, length:null, escape:''); // OK
fgetcsv($fp, length:null, escape:'"'); // OK
fgetcsv($fp, length:null, escape:'@@'); // ValueError Argument #5 ($escape) must be empty or a single character
```

## Standard

### Using the default value for $escape parameter is now deprecated

[fputcsv](https://www.php.net/manual/ja/function.fputcsv.php)・[fgetcsv](https://www.php.net/manual/ja/function.fgetcsv.php)・[str_getcsv](https://www.php.net/manual/ja/function.str-getcsv.php)の引数`$escape`は[必須になりました](https://wiki.php.net/rfc/deprecations_php_8_4#deprecate_proprietary_csv_escaping_mechanism)。

上の`SplFileObject::setCsvControl()`と全く同じ理由です。

### Calling stream_context_set_option() with 2 arguments is deprecated

[stream_context_set_option](https://www.php.net/manual/ja/function.stream-context-set-option.php)に2引数を渡す方のシグネチャが削除されました。
4引数のほうを使うか、[stream_context_set_options](https://www.php.net/manual/ja/function.stream-context-set-options.php)を使いましょう。

### Unserializing strings using the uppercase 'S' tag is deprecated

[unserialize](https://www.php.net/manual/ja/function.unserialize.php)のパーサメカニズムのうち、`S`タグの対応が[削除されました](https://wiki.php.net/rfc/deprecations_php_8_4#unserialize_s_s_tag)。

これはそもそもリリースされていないバージョンのPHP6でしか生成されないタグであり、シリアライズされた文字列を直接編集しないかぎり絶対に出てこないので、一般ユーザには全く影響しないでしょう。

```php
unserialize('S:1:"a";'); // Unserializing the 'S' format is deprecated
```

## XML

### The xml_set_object() function has been deprecated


[xml_set_object()](https://www.php.net/manual/ja/function.xml-set-object.php)は[削除されました](https://wiki.php.net/rfc/deprecations_php_8_4#xml_set_object_and_xml_set_handler_with_string_method_names)。

かわりに[xml_set_XXX_handler](https://www.php.net/manual/ja/function.xml-set-default-handler.php)を使いましょう。

### Passing non-callable strings to the xml_set_*_handler() functions is now deprecated

[xml_set_XXX_handler](https://www.php.net/manual/ja/function.xml-set-default-handler.php)の引数`$handler`にcallable以外を渡すことが禁止されました。

これまでは文字列を渡すと、`xml_set_object()`で渡したオブジェクトの中の該当メソッドが実行されていました。
これは良く使われているオブジェクト呼び出し構文`[インスタンス名, メソッド名]`とかけ離れていてわかりにくいため、機能を削除します。


# Changed Functions

変更のあった関数。

## Core

### trigger_error() and user_error() now have a return type of true instead of bool

[trigger_error](https://www.php.net/manual/ja/function.trigger-error.php)・[user_error](https://www.php.net/manual/ja/function.user-error.php)の返り値の型がboolからtrueになりました。

元々trueしか返さなかったので実情に合わせただけです。

## DOM

### DOMDocument::registerNodeClass() now has a tentative return type of true

[DOMDocument::registerNodeClass()](https://www.php.net/manual/ja/domdocument.registernodeclass.php)の返り値の型がboolからtrueになりました。

## Hash

### Changed the return type of hash_update() to true

[hash_update()](https://www.php.net/manual/ja/function.hash-update.php)の返り値の型がboolからtrueになりました。


## Intl

### NumberFormatter::ROUND_TOWARD_ZERO and NumberFormatter::ROUND_AWAY_FROM_ZERO have been added

[NumberFormatter](https://www.php.net/manual/ja/class.numberformatter.php)にクラス定数ROUND_TOWARD_ZEROとROUND_AWAY_FROM_ZEROが追加されました。
値はROUND_DOWN・ROUND_UPと同じです。
これは[round()](https://www.php.net/manual/ja/function.round.php)に追加された定数RoundingMode::TowardsZero等と形を合わせたものとなります。


### ResourceBundle::get() now has a tentative return type of: ResourceBundle|array|string|int|null

[ResourceBundle::get](https://www.php.net/manual/ja/resourcebundle.get.php)の返り値の型が`ResourceBundle|array|string|int|null`になりました。

ちょっとどうなんだという型ですが、これは暫定的な値のようです。

### The idn_to_ascii() and idn_to_utf8() now always throw ValueErrors if the $domain name is empty or too long, and if $variant is not INTL_IDNA_VARIANT_UTS46

[idn_to_ascii](https://www.php.net/manual/ja/function.idn-to-ascii.php)・[idn_to_utf8](https://www.php.net/manual/ja/function.idn-to-utf8.php)は、cvariantがINTL_IDNA_VARIANT_UTS46でなければValueErrorを出すようになりました。

## LibXML

### libxml_set_streams_context() now immediately throws a TypeError when a non-stream-context resource is passed to the function

[libxml_set_streams_context()](https://www.php.net/manual/ja/function.libxml-set-streams-context.php)のエラーが発生するタイミングが早まりました。
これまでは引数が正しくなかった場合、生成されたストリームを実際に使おうとした段階でようやくエラーが発生していたのですが、今後は`libxml_set_streams_context()`を呼んだ時点ですぐ発生します。

## MBString

### The behavior of mb_strcut is more consistent now on invalid UTF-8 and UTF-16 strings

[mb_strcut()](https://www.php.net/manual/ja/function.mb-strcut.php)に、正しくないフォーマットのUTF-8文字列を渡したときの挙動が一貫性を持つようになりました。
正しいフォーマットのUTF-8については動作に変更ありません。

正しくないんだからどうでもいい気はしますけどね。

## ODBC

### Parameter $row of odbc_fetch_object(), odbc_fetch_array(), and odbc_fetch_into() now has a default value of null

[odbc_fetch_object()](https://www.php.net/manual/ja/function.odbc-fetch-object.php)・[odbc_fetch_array()](https://www.php.net/manual/ja/function.odbc-fetch-array.php)・[odbc_fetch_into()](https://www.php.net/manual/ja/function.odbc-fetch-into.php)の引数`$row`のデフォルト値がnullになりました。

[odbc_fetch_row()](https://www.php.net/manual/ja/function.odbc-fetch-row.php)はnullだったので、これと合わせました。
これまではそれぞれ-1,-1,0とバラバラでした。

## OpenSSL

### The extra_attributes parameter in openssl_csr_new sets CSR attributes

[openssl_csr_new](https://www.php.net/manual/ja/function.openssl-csr-new.php)の引数`$extra_attributes`はCSR属性を設定するようになりました。

これまでは誤ってDN Subjectを設定していたそうです。ええ……

まあPHPでSSL証明書をどうこうするなんて普通はやらないですよね。

### The dn parameter in openssl_csr_new allows setting array of values for a single entry

[openssl_csr_new()](https://www.php.net/manual/ja/function.openssl-csr-new.php)の引数`$distinguished_names`は、ひとつの項目に値を配列で設定できるようになりました。

### New serial_hex parameter added to openssl_csr_sign to allow setting serial number in the hexadecimal format

[openssl_csr_sign()](https://www.php.net/manual/ja/function.openssl-csr-sign.php)に引数`$serial_hex`が追加されました。

シリアル番号を16進形式で設定できます。
引数`$serial`との違いはよくわからない。


### Parsing ASN.1 UTCTime by openssl_x509_parse fails if seconds are omitted for OpenSSL version below 3.2 (-1 is returned for such fields)

OpenSSL3.2未満で、秒数が入っていないASN.1 UTCTimeについては、[openssl_x509_parse()](https://www.php.net/manual/ja/function.openssl-x509-parse.php)で該当フィールドのパースが失敗します。
OpenSSL3.3以上では証明書の読み込み自体ができません。


## Output

### Output handler status flags passed to the flags parameter of ob_start are now cleared

[ob_start()](https://www.php.net/manual/ja/function.ob-start.php)の出力ハンドラについて、引数`$flags`で渡したステータスフラグがクリアされるようになりました。

とあるんだけど意味が[よく](https://www.php.net/manual/ja/migration84.other-changes.php#migration84.other-changes.core.output)[わからない](https://www.php.net/manual/en/migration84.other-changes.php#migration84.other-changes.core.output)。

## PDO

### getAttribute, enabled to get the value of ATTR_STRINGIFY_FETCHES

[PDO::getAttribute()](https://www.php.net/manual/ja/pdo.getattribute.php)で[ATTR_STRINGIFY_FETCHES](https://www.php.net/manual/ja/pdo.setattribute.php)が取得できるようになりました。

## PDO_FIREBIRD

### getAttribute, enabled to get values of FB_ATTR_DATE_FORMAT, FB_ATTR_TIME_FORMAT, FB_ATTR_TIMESTAMP_FORMAT.

[PDO::getAttribute()](https://www.php.net/manual/ja/pdo.getattribute.php)で[FB_ATTR_DATE_FORMAT・FB_ATTR_TIME_FORMAT・FB_ATTR_TIMESTAMP_FORMAT](https://www.php.net/manual/ja/ref.pdo-firebird.php)が取得できるようになりました。

### Added new attributes to specify transaction isolation level and access mode

トランザクション分離レベルとアクセスレベルを設定するための新しい属性と定数が追加されました。

```php
$dbh->setAttribute(PDO\Firebird::TRANSACTION_ISOLATION_LEVEL, PDO\Firebird::REPEATABLE_READ);
$dbh->setAttribute(PDO\Firebird::WRITABLE_TRANSACTION, false);
```

トランザクション分離レベルは`Pdo\Firebird::READ_COMMITTED`・`Pdo\Firebird::REPEATABLE_READ`・`Pdo\Firebird::SERIALIZABLE`の3種類、アクセスレベルはtrue=読み書き、false=読み込みオンリーの2種類です。

### When using persistent connections, there is now a liveness check in the constructor

永続的接続を使う際、コンストラクタでliveness checkが行われるようになりました。

liveness checkってなんだ？

### added static method Pdo\Firebird::getApiVersion() to obtain that value

FB_API_VERを取得するstaticメソッド`Pdo\Firebird::getApiVersion()`が追加されました。
FB_API_VERはphpinfoにも出力されます。

### Five new data types are now available: INT128, DEC16, DEC34, TIMESTAMP_TZ, TIME_TZ

Firebird4.0以降で、5種類のデータ型が追加されました。
`INT128`・`DEC16`・`DEC34`・`TIMESTAMP_TZ`・`TIME_TZ`。


## PDO_MYSQL

### getAttribute, enabled to get the value of ATTR_FETCH_TABLE_NAMES

[PDO::getAttribute()](https://www.php.net/manual/ja/pdo.getattribute.php)で[ATTR_FETCH_TABLE_NAMES](https://www.php.net/manual/ja/pdo.constants.php)が取得できるようになりました。

## PDO_PGSQL

### getAttribute() can now retrieve the memory usage of query results

[PDO::getAttribute()](https://www.php.net/manual/ja/pdo.getattribute.php)で[PDO::PGSQL_ATTR_RESULT_MEMORY_SIZE](https://www.php.net/manual/ja/ref.pdo-pgsql.php)が取得できるようになりました。
クエリのメモリ使用量を確認できます。

### If the column is of FLOAT4OID/FLOAT8OID type, query returns it as a float instead of a string

FLOAT4OID・FLOAT8OID型のカラムの型がstringからfloatになりました。

## PgSQL

### pg_select, the conditions arguments accepts an empty array and is optional.


[pg_select()](https://www.php.net/manual/ja/function.pg-select.php)の引数`$conditions`がオプショナル化され、空配列も受け入れるようになりました。

## Phar

### Phar::setAlias() and Phar::setDefaultStub() methods now have a tentative return type of true instead of bool

[Phar::setAlias()](https://www.php.net/manual/ja/phar.setalias.php)・[Phar::setDefaultStub()](https://www.php.net/manual/ja/phar.setdefaultstub.php)の返り値の型がboolからtrueになりました。

## POSIX

### posix_isatty now sets the error number when the file descriptor/stream argument is invalid

[posix_isatty()](https://www.php.net/manual/ja/function.posix-isatty.php)は引数`$file_descriptor`が無効な場合にエラー番号を設定するようになりました。

設定って何処に設定するんだ？返り値？

## Reflection

### ReflectionGenerator::getFunction() may now be called after the generator finished executing

既に使い果たしたジェネレータからも[ReflectionGenerator::getFunction](https://www.php.net/manual/ja/reflectiongenerator.getfunction.php)を呼ぶことができるようになりました。

```php
function gen(){
    yield 1;
}
$gen = gen();
foreach($gen as $v){
    var_dump($v);
}
$reflectionGen = new ReflectionGenerator($gen);
var_dump($reflectionGen->getFunction());

// PHP8.4 object(ReflectionFunction)
// PHP8.3 Uncaught ReflectionException: Cannot create ReflectionGenerator based on a terminated Generator
```

## Sockets

### Parameter $backlog of socket_create_listen() now has a default value of SOMAXCONN

[socket_create_listen](https://www.php.net/manual/ja/function.socket-create-listen.php)の引数`$backlog`のデフォルト値が定数SOMAXCONNになりました。

これまでは128固定でした。

## SPL

### SplPriorityQueue::insert() and SplPriorityQueue::recoverFromCorruption() now has a tentative return type of true

[SplPriorityQueue::insert()](https://www.php.net/manual/ja/splpriorityqueue.insert.php)・[SplPriorityQueue::recoverFromCorruption()](https://www.php.net/manual/ja/splpriorityqueue.recoverfromcorruption.php)の返り値の型がboolからtrueになりました。


### SplHeap::insert() and SplHeap::recoverFromCorruption() now has a tentative return type of true instead of bool

[SplHeap::insert()](https://www.php.net/manual/ja/splheap.insert.php)・[SplHeap::recoverFromCorruption()](https://www.php.net/manual/ja/splheap.recoverfromcorruption.php)の返り値の型がboolからtrueになりました。

## Standard

### The internal implementation for rounding to integers has been rewritten

丸め関数の内部実装をリファクタリングし、いくつかのバグが修正されました。
より正しい方向に値が変わることがあります。

```php
var_dump(round(0.49999999999999994));

// PHP8.4 0
// PHP8.3 1
```


###  The $mode parameter of the round() function has been widened to RoundingMode|int, accepting instances of a new RoundingMode enum

[round()](https://www.php.net/manual/ja/function.round.php)の引数`$mode`の型が`int`から`RoundingMode|int`に[なりました](https://wiki.php.net/rfc/correctly_name_the_rounding_mode_and_make_it_an_enum)。

###  Four new modes have been added to the round() function

[round()](https://www.php.net/manual/ja/function.round.php)の丸めモードが[4種類追加されました](https://wiki.php.net/rfc/new_rounding_modes_to_round_function)。

・RoundingMode::PositiveInfinity 引数より大きい最小の整数に丸める。
・RoundingMode::NegativeInfinity 引数より小さい最大の整数に丸める。
・RoundingMode::AwayFromZero ゼロから離れた方に丸める。
・RoundingMode::TowardsZero ゼロに近い方に丸める。


###  Fixed a bug caused by "pre-rounding" of the round() function

round関数の`pre-rounding`に起因するバグが修正されました。

たとえば`0.285`は内部的には`0.28499999999999998`なんだけど計算しやすいように事前に`0.29`にしてから計算していた、みたいなことをやっていたらしいんだけど、これをなくしたようです。
結果として、`round()`はたまに正しくない値を返してくるエッジケースがあるのですが、その頻度が減ります。

###  The maximum precision that can be handled by round() has been extended by one digit

round関数の有効桁数が1桁増えました。

```php
var_dump(round(4503599627370495.5));

// PHP8.4 4503599627370496
// PHP8.3 4503599627370495.5
```

###  The default value of the 'cost' option for PASSWORD_BCRYPT for password_hash() has been increased from '10' to '12'.

[password_hash()](https://www.php.net/manual/ja/function.password-hash.php)のアルゴリズムPASSWORD_BCRYPTについて、コストのデフォルト値が[10から12になりました](https://wiki.php.net/rfc/bcrypt_cost_2023)。


###  debug_zval_dump() now indicates whether an array is packed.

[debug_zval_dump()](https://www.php.net/manual/ja/function.debug-zval-dump.php)は配列がpackedされているかを出力するようになりました。

```php
debug_zval_dump([2=>1, 4=>1]); // packed refcount{}
debug_zval_dump([4=>1, 2=>1]); // refcount{}
```

[このスライド](https://files.speakerdeck.com/presentations/8d928d4d7e9848208faec0954240a196/slide_37.jpg)だと0スタート昇順の場合のみpackedと書いてあるんだけど、試してみたら0スタートでなくても抜けがあってもpakedになるみたいでした。
逆順ではさすがにpackedになりませんでした。

###  long2ip() now returns string instead of string|false

[long2ip()](https://www.php.net/manual/ja/function.long2ip.php)の返り値の型が`string|false`から`string`になりました。

###  output_add_rewrite_var() now uses url_rewriter.hosts instead of session.trans_sid_hosts for selecting hosts that will be rewritten

[output_add_rewrite_var()](https://www.php.net/manual/ja/function.output-add-rewrite-var.php)は、書き替えるホストの判断に`session.trans_sid_hosts`ではなく`url_rewriter.hosts`を使うようになりました。

###  highlight_string() now has a return type of string|true instead of string|bool.

[highlight_string()](https://www.php.net/manual/ja/function.highlight-string.php)の返り値の型が`string|bool`から`string|true`になりました。

###  print_r() now has a return type of string|true instead of string|bool.

[print_r()](https://www.php.net/manual/ja/function.print-r.php)の返り値の型が`string|bool`から`string|true`になりました。

# New Functions

新しく追加された関数。

## Core

### request_parse_body()

関数request_parse_body()が追加されました。

POST以外のリクエストメソッドでも[リクエストボディを取得](https://qiita.com/rana_kualu/items/8a95669ebbfd19e27da9)できます。

## BCMath

### Added bcfloor(), bcceil(), bcround()

[BCMath](https://www.php.net/manual/ja/book.bc.php)に丸め関数[bcfloor()・bcceil()・bcround()が追加](https://wiki.php.net/rfc/adding_bcround_bcfloor_bcceil_to_bcmath)されました。

### Added bcdivmod()

[BCMath](https://www.php.net/manual/ja/book.bc.php)に商と余りを取得する関数[bcdivmod()が追加](https://wiki.php.net/rfc/add_bcdivmod_to_bcmath)されました。

## Date

### Added static methods DateTime[Immutable]::createFromTimestamp(int|float $timestamp): static.

[タイムスタンプからDateTimeを生成する関数](https://php.watch/versions/8.4/datetime-createFromTimestamp)です。

### Added method DateTime[Immutable]::getMicrosecond(): int

[マイクロ秒を取得する関数](https://php.watch/versions/8.4/date-datetime-get-setMicrosecond)です。

### Added method DateTime[Immutable]::setMicrosecond(int $microsecond): static.

[マイクロ秒を設定する関数](https://php.watch/versions/8.4/date-datetime-get-setMicrosecond)です。

## DOM

### Added DOMNode::compareDocumentPosition().

[ふたつのDOMノードのどちらが先にあるか調べます](https://www.php.net/manual/ja/domnode.comparedocumentposition.php)。

### Added DOMXPath::registerPhpFunctionNS()

[XPath式内でPHP関数を使える](https://wiki.php.net/rfc/improve_callbacks_dom_and_xsl)ようになります。

既にほぼ同じ関数[DOMXPath::registerPhpFunctions](https://www.php.net/manual/ja/domxpath.registerphpfunctions.php)がありますが、こちらは文字列のみ、registerPhpFunctionNSはコールバックを渡せるという違いがあるようです。
DOMは全然使わないので正直よくわかりません。

### Added DOMXPath::quote() to quote a string for use in an XPath expression

XPath用のエスケープ関数[DOMXPath::quote](https://www.php.net/manual/ja/domxpath.quote.php)が追加されました。

```php:例
$query = "//book[@name=" . DOMXPath::quote($text) . "]";
```

## Hash

### Added HashContext::__debugInfo().

メソッド`HashContext::__debugInfo()`が追加されました。

`__debugInfo`は`var_dump`の出力を変更できるマジックメソッドです。
従ってHashContextの出力が変更されるはずですが、このメソッドなぜか情報が一切出てこないので詳細不明。

## Intl

### Added IntlTimeZone::getIanaID()/intltz_get_iana_id() to the IANA identifier from a given timezone

タイムゾーン識別子を正規化して返すメソッド`IntlTimeZone::getIanaID()`が追加されました。

```php
var_dump(IntlTimeZone::getIanaID('Japan')); // Asia/Tokyo
```

単に[ICUの同名関数](https://unicode-org.github.io/icu-docs/apidoc/dev/icu4c/classicu_1_1TimeZone.html#a7e182f60aa75c78a623065ad8470d290)のラッパーであり、[変換リスト](https://data.iana.org/time-zones/tzdb/backward)を通しているだけのようです。


### Added grapheme_str_split which allow to support emoji and Variation Selectors

関数grapheme_str_splitが追加されました。

[絵文字を正しく分割できる関数](https://qiita.com/rana_kualu/items/007a5438b2d477c34502)です。

```php
var_dump(grapheme_str_split('👨‍👩‍👦‍👦')); // [👨‍👩‍👦‍👦]
```


### Added IntlDateFormatter::parseToCalendar which behaves like IntlDateFormatter::parse except the time zone is updated

メソッド`IntlDateFormatter::parseToCalendar()`が追加されました。

[IntlDateFormatter::parse](https://www.php.net/manual/ja/intldateformatter.parse.php)と同じだけどタイムゾーンを考慮する？
よくわからない。
そもそもIntlの日時オブジェクト自体が地獄みたいな仕様だから(PHPのせいではなくIntlのせい)使うことないからいいや。


### Added SpoofChecker::setAllowedChars to limit the range of unicode chars

メソッド`SpoofChecker::setAllowedChars()`が追加されました。

UNICODE文字範囲を制限するということらしいですがこれまたよくわかりません。
これも[ICUライブラリからそのままもってきた](https://unicode-org.github.io/icu-docs/apidoc/dev/icu4j/com/ibm/icu/text/SpoofChecker.html)関数だと思われます。


## MBString

### Added mb_trim, mb_ltrim and mb_rtrim functions

関数`mb_trim()`・`mb_ltrim()`・`mb_rtrim()`が追加されました。

[マルチバイトtrim関数](https://qiita.com/rana_kualu/items/87bc5dd0396103bd7a32)です。

### Added mb_ucfirst and mb_lcfirst functions

関数`mb_ucfirst()`・`mb_lcfirst()`が追加されました。

[マルチバイトucfirst関数](https://tekitoh-memdhoi.info/views/894)です。

## OPCache

### Added opcache_jit_blacklist function. It allows skipping the tracing JIT execution of select functions

関数`opcache_jit_blacklist()`が追加されました。

この関数で指定した関数は、JITの適用外になるみたいです。

## PCNTL

[pcntl](https://www.php.net/manual/ja/book.pcntl.php)ぜんぜんわからん。

### Added pcntl_setns allowing a process to be reassociated with a namespace in order to share resources with other processes within this context

関数`pcntl_setns()`が追加されました。

プロセスを既存の名前空間に関連付けられるようにします。
[pcntl_unshare](https://www.php.net/manual/ja/function.pcntl-unshare.php)の逆みたいです。

### Added pcntl_getcpuaffinity to get the cpu(s) bound to a process and pcntl_setcpuaffinity to bind 1 or more cpus to a process.

関数`pcntl_getcpuaffinity()`・`pcntl_setcpuaffinity()`が追加されました。

pcntl_setcpuaffinityでプロセスにCPUをバインドし、pcntl_getcpuaffinityはプロセスにバインドされているCPUを取得します。

### Added pcntl_getcpu to get the cpu id from where the current process runs.

関数`pcntl_getcpu()`が追加されました。

現在プロセスが実行されているCPU IDを取得します。

### Added pcntl_getqos_class to get the QoS level (aka performance and related energy consumption) of the current process and pcntl_setqos_class to set it

関数`pcntl_getqos_class()`・`pcntl_setqos_class()`が追加されました。

pcntl_setqos_classで現在のプロセスのQoSレベルを設定し、pcntl_getqos_classは現在の設定値を取得します。

QoSといっても[タスクの優先順位](https://developer.apple.com/documentation/dispatch/dispatchqos/qosclass)についての[話のようです](https://github.com/php/php-src/commit/d40726670fd2915dcd8076738c56596e7c877b58)。


### Added pcntl_waitid to obtain status information pertaining to termination, stop, and/or continue events in one of the caller's child processes

関数`pcntl_waitid()`が追加されました。

子プロセスの状態が変化するまで待機する関数のようです。


## PDO_PGSQL

### Added Pdo\Pgsql::setNoticeCallback() to allow a callback to be triggered on every notice sent

メソッド`Pdo\Pgsql::setNoticeCallback()`が追加されました。

NOTICEが発行された際に呼び出されるコールバックを登録できます。

## PgSQL

MySQLしか使ってないからPostgresの理解はふわふわです。

### Added pg_change_password to alter a given user's password.

関数`pg_change_password()`が追加されました。

指定ユーザのパスワードを変更します。

### Added pg_put_copy_data to send COPY commands and pg_put_copy_end to send end-of-data to the server

関数`pg_put_copy_data()`・`pg_put_copy_end()`が追加されました。

[COPY](https://www.postgresql.jp/docs/9.4/sql-copy.html)コマンドの開始と終了を送信する用です。

### Added pg_socket_poll to check if there is any read and/or write events with an optional timeout

関数`pg_socket_poll()`が追加されました。

読み取りイベント・書き込みイベントが残っているかを調べるようです。

### Added pg_jit to get informations on the server JIT support.

関数`pg_jit()`が追加されました。

サーバが[JIT](https://www.postgresql.jp/docs/15/jit-reason.html)をサポートしているかの情報を取得します。

### Added pg_set_chunked_rows_size to allow to fetch results in chunk of max N rows

関数`pg_set_chunked_rows_size()`が追加されました。

チャンクモードで結果を取得する行数を設定します。
大きな結果を取得したいときに少しずつ取りに行くあれです。

### Added pg_result_memory_size to get the visibility the memory used by a query result.

関数`pg_result_memory_size()`が追加されました。

SQLクエリのメモリ使用量を調べることができます。

## Reflection

### Multiple methods related to lazy objects were introduced

[遅延初期化](https://qiita.com/rana_kualu/items/b195b1adc60b763843d9#lazy-objects)に関するメソッドが追加されました。

・ReflectionClass::newLazyGhost()
・ReflectionClass::newLazyProxy()
・ReflectionClass::resetAsLazyGhost()
・ReflectionClass::resetAsLazyProxy()
・ReflectionClass::isUninitializedLazyObject()
・ReflectionClass::initializeLazyObject()
・ReflectionClass::markLazyObjectAsInitialized()
・ReflectionClass::getLazyInitializer()
・ReflectionProperty::skipLazyInitialization()
・ReflectionProperty::setRawValueWithoutLazyInitialization()

### ReflectionClassConstant::isDeprecated() was introduced.

メソッド`ReflectionClassConstant::isDeprecated()`が追加されました。

`@Deprecated`を検出します。

### ReflectionGenerator::isClosed() was introduced.

メソッド`ReflectionGenerator::isClosed()`が追加されました。

そのジェネレータが既に終了しているかを調べます。

### ReflectionProperty::isDynamic() was introduced.

メソッド`ReflectionProperty::isDynamic()`が追加されました。

そのプロパティが[動的プロパティかを調べます](https://github.com/php/php-src/issues/15754)。

```php
$hoge = new class{
    public $s = 1;
};
$hoge->d = 1;

$reflector = new ReflectionObject($hoge);
var_dump($reflector->getProperty('s')->isDynamic()); // false
var_dump($reflector->getProperty('d')->isDynamic()); // true
```

[動的プロパティはPHP9.0で使えなくなる](https://qiita.com/rana_kualu/items/53012c8f84e0f92220c1)ことが決定しています。
従ってLinterや移行支援ツールにとって有用となるでしょう。

## Sodium

### Added the sodium_crypto_aead_aegis128l_*() and sodium_crypto_aead_aegis256l_*() functions

関数`sodium_crypto_aead_aegis128l_*()`・`sodium_crypto_aead_aegis256l_*()`が追加されました。

[libsodium 1.0.19](https://www.nuget.org/packages/libsodium/1.0.19.1)で[AEGIS](https://doc.libsodium.org/secret-key_cryptography/aead/aegis-256)がサポートされたので、その対応のためです。

しかしアルゴリズムごとに[個別に関数を作っている](https://www.php.net/manual/ja/ref.sodium.php)せいで関数一覧がえらいことになっているので早くオブジェクトにしてくれって思いますよね。


### sodium_crypto_aead_aes256gcm_*() functions are now enabled on aarch64 CPUs with the ARM cryptographic extensions.

関数`sodium_crypto_aead_aes256gcm_*()`がaarch64 CPUでも動くようになりました。
これ新関数の段に書いてあるのですが、PHP7.2からあったので新関数じゃないですよね。

## SPL

### Added seek() method to SplObjectStorage, now it implements SeekableIterator

メソッド`SplObjectStorage::seek()`が追加されました。

## SOAP

### Added SoapServer::__getLastResponse()

メソッドSoapServer::__getLastResponse()が追加されました。

[SoapServer::__construct()](https://www.php.net/manual/ja/soapserver.construct.php)の引数`$options`でtrace=trueになっていた場合に、最終応答を返します。

## Standard

### Added the http_get_last_response_headers() and http_clear_last_response_headers() that allows retrieving the same content as the magic $http_response_header variable.

関数`http_get_last_response_headers()`・`http_clear_last_response_headers()`が追加されました。

`file_get_contents()`した直後に呼ぶと、そのリクエストで発生したヘッダを取得することができます。
謎変数`$http_response_header`を[削除するための布石](https://qiita.com/rana_kualu/items/f16cf9757139fcba4191)です。

### Added function fpow() following rules of IEEE 754.

関数`fpow()`が追加されました。

[IEEE754に従うpow()](https://wiki.php.net/rfc/raising_zero_to_power_of_negative_number)です。

### Added functions array_find(), array_find_key(), array_all(), and array_any()

関数`array_find()`・`array_find_key()`・`array_all()`・`and array_any()`が追加されました。

配列を[コールバックで任意検索できる](https://qiita.com/rana_kualu/items/6acf9064a55d7f50b4b8)便利な関数群です。

```php
$array = [
    'a' => 'dog',
    'b' => 'cat',
    'c' => 'cow',
    'd' => 'duck',
    'e' => 'goose',
    'f' => 'elephant'
];
 
// 5文字以上の値を検索
var_dump(array_find($array, function (string $value) {
    return strlen($value) > 4;
})); // string(5) "goose"

// 1文字目がキーになっている値を検索してキーを返す
var_dump(array_find_key($array, function (string $value, $key) {
   return $value[0] === $key;
})); // string(1) "c"

// 5文字以上の値が存在するか
var_dump(array_any($array, function (string $value) {
    return strlen($value) > 5;
})); // bool(true)

// 全ての値が6文字以上か
var_dump(array_all($array, function (string $value) {
    return strlen($value) > 5;
})); // bool(false)
```

## Tidy

### Added tidyNode::getNextSibling() and tidyNode::getPreviousSibling().

メソッド`tidyNode::getNextSibling()`・`tidyNode::getPreviousSibling()`が追加されました。

それぞれ[次の兄弟ノード](https://www.php.net/manual/ja/tidynode.getnextsibling.php)、[手前の兄弟ノード](https://www.php.net/manual/ja/tidynode.getprevioussibling.php)を返します。


## XMLReader

### Added XMLReader::fromStream(), XMLReader::fromUri(), XMLReader::fromString()

メソッド`XMLReader::fromStream()`・`XMLReader::fromUri()`・`XMLReader::fromString()`が追加されました。

[元々のRFC](https://wiki.php.net/rfc/xmlreader_writer_streams)はストリームからXMLを作る方法がないのでfromStreamを追加したいというものでした。
名前を揃えて[XMLReader::open](https://www.php.net/manual/ja/xmlreader.open.php)のエイリアスfromUri、[XMLReader::XML](https://www.php.net/manual/ja/xmlreader.xml.php)のエイリアスfromStringも追加されました。
実際はエイリアスではなく微妙に違うみたいですが。

## XMLWriter

メソッド`XMLWriter::toStream()`・`XMLWriter::toUri()`・`XMLWriter::toMemory()`が追加されました。

動機はXMLReaderと同じです。

## XSL

### Added XSLTProcessor::registerPhpFunctionNS()

メソッド`XSLTProcessor::registerPhpFunctionNS()`が追加されました。

`DOMXPath::registerPhpFunctionNS()`と同じです。


# New Classes and Interfaces

新しいクラス・インターフェイス。

## BCMath

### Added BcMath\Number class

クラス`BcMath\Number`が[追加されました](https://wiki.php.net/rfc/support_object_type_in_bcmath)。

これはイミュータブルであり、BCMath関数の全てをメソッドとして持っています。

```php
$a = new BcMath\Number(100);
$b = $a->add(50);
$c = $b->divmod(40);
var_dump($c); [BcMath\Number(3), BcMath\Number(30)]
```

手続き型インターフェイスしか存在しない特殊な[GMPクラス](https://www.php.net/manual/ja/class.gmp.php)と異なり、こちらは思った通りの操作が行えるオブジェクトです。

## Core

### RequestParseBodyException

[request_parse_body()](https://qiita.com/rana_kualu/items/8a95669ebbfd19e27da9)で発生することがある例外です。


### #[\Deprecated] attribute.

[アトリビュートDeprecated](https://qiita.com/rana_kualu/items/a1b420834725f9ff3fc3)です。

## DBA

### Dba\Connection opaque object replacing DBA resources

[DBA](https://www.php.net/manual/ja/book.dba.php)がリソースからDba\Connectionオブジェクトになりました。

## DOM

### Implemented DOM HTML5 parsing and serialization.

[DOM関連クラスが複数追加されました](https://wiki.php.net/rfc/domdocument_html5_parser)。

これまでPHPが使っていたDOMライブラリはHTML5に対応しておらず、HTML5の読み書きが困難でした。
そのため新たなライブラリを導入し、PHPからは`Dom\HTMLDocument`・`Dom\XMLDocument`で使えるようにします。

### Implemented opt-in ext/dom spec compliance RFC.

[DOM関連クラスが複数追加されました](https://wiki.php.net/rfc/opt_in_dom_spec_compliance)。

古いDOMを、HTML5対応の新しいDOMドキュメントに変換するためのものです。

### Implemented "New ext-dom features in PHP 8.4" RFC.

[DOM関連クラスがさらに追加されました](https://wiki.php.net/rfc/dom_additions_84)。

querySelectorなどのこれまでなかった便利機能が追加されます。


## ODBC

### Odbc\Connection
### Odbc\Result

[ODBC](https://www.php.net/manual/ja/book.uodbc.php)がリソースからオブジェクトになりました。

## PDO

### Pdo\DbLib
### Pdo\Firebird
### Pdo\Mysql
### Pdo\Odbc
### Pdo\Pgsql
### Pdo\Sqlite

[PDO](https://www.php.net/manual/ja/class.pdo.php)がドライバごとの専用オブジェクトを使えるようになりました。

## Reflection

### ReflectionConstant

定数に関するリフレクションを表すクラスです。

## SOAP

### Soap\Url
### Soap\Sdl

## Standard

### StreamBucket

[stream_bucket_new](https://www.php.net/manual/ja/function.stream-bucket-new.php)の返り値として使われます。
これまではstdClassでした。

# Removed Extensions and SAPIs

削除されたエクステンションなど。

## IMAP

[IMAP](https://www.php.net/manual/ja/book.imap.php)は同梱されなくなりました。
当面はPECLからインストールできます。

IMAPが使っているライブラリ[uw-imap/imap](https://github.com/uw-imap/imap)は更新が滞っており、OAuthに対応していないのでGmailが使えません。

## OCI8 / PDO_OCI

[OCI8](https://www.php.net/manual/ja/book.oci8.php)および[PDO_OCI](https://www.php.net/manual/ja/ref.pdo-oci.php)は同梱されなくなりました。
当面はPECLからインストールできます。

OCIが使っているライブラリ[Oracle Instant Client](https://www.oracle.com/database/technologies/instant-client.html)は非常にバグが多く、使い物にならないそうです。

## PSpell

[PSpell](https://www.php.net/manual/ja/book.pspell.php)は同梱されなくなりました。
当面はPECLからインストールできます。

PSpellが使っている[ライブラリpspell](https://sourceforge.net/projects/pspell/)は、最終更新が2001年です。


# Other Changes to Extensions

その他の変更。

## Curl

### The Curl extension now requires at least libcurl 7.61.0.

Curlエクステンションが要求する最低バージョンが[libcurl 7.61.0](https://daniel.haxx.se/blog/2018/07/11/curl-7-61-0/)になりました。

### The CURLOPT_DNS_USE_GLOBAL_CACHE Curl option no longer has any effect, and is silently ignored

[CURLOPT_DNS_USE_GLOBAL_CACHE](https://curl.se/libcurl/c/CURLOPT_DNS_USE_GLOBAL_CACHE.html)は黙って無視されます。

これはlibcurl側の変更に合わせたものです。
CURLOPT_DNS_USE_GLOBAL_CACHEはlibcurl 7.11.1で非推奨になり、libcurl 7.62.0で削除されました。

## GMP

### Casting a GMP object to bool is now possible instead of emitting a E_RECOVERABLE_ERROR

GMPオブジェクトを[boolキャストできるようになりました](https://wiki.php.net/rfc/fix_up_bcmath_number_class)。
int型と同様0はfalse、それ以外は全てtrueです。

これまではE_RECOVERABLE_ERRORが発生していました。

## Intl

### The behaviour of Intl class has been normalized to always throw Error exceptions when attempting to use a non-initialized object

[Intlクラス](https://www.php.net/manual/ja/book.intl.php)は、初期化せずに呼び出すとErrorを出すようになりました。
とあるんだけど何のことかわかんない。
non-initialized objectってなんだよ。


## LibXML

### The libxml extension now requires at least libxml2 2.9.4

libxmlエクステンションが要求する最低バージョンが[libxml2 2.9.4](https://www.linuxfromscratch.org/blfs/view/8.1/general/libxml2.html)になりました。

## MBString

### Unicode data tables have been updated to Unicode 16.0

Unicodeテーブルが[Unicode 16.0](https://blog.unicode.org/2024/09/announcing-unicode-standard-version-160.html)になりました。

## Mysqlnd

### Support for the new VECTOR data type from MySQL 9

[MySQL 9.0](https://dev.mysql.com/doc/refman/9.0/en/vector.html)以上でVECTOR型をサポートしました。

## OpenSSL

### The OpenSSL extension now requires at least OpenSSL 1.1.1

OpenSSLエクステンションが要求する最低バージョンが[OpenSSL 1.1.1](https://openssl-library.org/news/openssl-1.1.1-notes/index.html)になりました。

OpenSSL1系は既にサポート終了しているので、できれば[3にさっさと上げてしまう](https://openssl-library.org/source/index.html)とよいでしょう。


## PDO_PGSQL / PgSQL

### The pdo_pgsql extension now requires at least libpq 10.0

pdo_pgsqlエクステンションが要求する最低バージョンが[libpq 10.0](https://www.postgresql.org/docs/current/libpq.html)になりました。

## SPL

### Out of bounds accesses in SplFixedArray now throw an exception of type OutOfBoundsException instead of RuntimeException

[SplFixedArray](https://www.php.net/manual/ja/class.splfixedarray.php)で範囲外にアクセスした際のエラーがRuntimeExceptionからOutOfBoundsExceptionになりました。

ただしOutOfBoundsExceptionはRuntimeExceptionの子クラスなので、RuntimeExceptionをcatchしているコードはそのまま使えます。

## XSL

### The typed properties XSLTProcessor::$cloneDocument and XSLTProcessor::$doXInclude are now declared

プロパティ[XSLTProcessor::$cloneDocument](https://www.php.net/manual/ja/class.xsltprocessor.php#xsltprocessor.props.clonedocument)と[XSLTProcessor::$doXInclude](https://www.php.net/manual/ja/class.xsltprocessor.php#xsltprocessor.props.doxinclude)が実装されました。


## zlib

### The zlib extension now requires at least zlib 1.2.11

zlibエクステンションが要求する最低バージョンが[zlib 1.2.11](https://github.com/madler/zlib/releases/tag/v1.2.11)になりました。


# New Global Constants

新しいグローバル定数。
基本的には使用しているライブラリで定義されている定数をそのまま取り込んだものです。

PHP_OUTPUT_HANDLER_PROCESSED
PHP_SBINDIR
CURL_HTTP_VERSION_3
CURL_HTTP_VERSION_3ONLY
CURL_TCP_KEEPCNT
CURLOPT_PREREQFUNCTION
CURL_PREREQFUNC_OK
CURL_PREREQFUNC_ABORT
CURLOPT_SERVER_RESPONSE_TIMEOUT
CURLOPT_DEBUGFUNCTION
CURLINFO_TEXT
CURLINFO_HEADER_IN
CURLINFO_DATA_IN
CURLINFO_DATA_OUT
CURLINFO_SSL_DATA_OUT
CURLINFO_SSL_DATA_IN
CURLINFO_POSTTRANSFER_TIME_T
IntlDateFormatter::PATTERN
IntlChar::PROPERTY_IDS_UNARY_OPERATOR
IntlChar::PROPERTY_ID_COMPAT_MATH_START
IntlChar::PROPERTY_ID_COMPAT_MATH_CONTINUE
LDAP_OPT_X_TLS_PROTOCOL_MAX
LDAP_OPT_X_TLS_PROTOCOL_TLS1_3
LIBXML_RECOVER
LIBXML_NO_XXE
MYSQLI_TYPE_VECTOR
X509_PURPOSE_OCSP_HELPER
X509_PURPOSE_TIMESTAMP_SIGN
Pcntl\QosClass::Background (macOs only)
Pcntl\QosClass::Default (macOs only)
Pctnl\QosClass::UserInteractive (macOs only)
Pcntl\QosClass::UserInitiated (macOs only)
Pcntl\QosClass::Utility (macOs only)
SIGCKPT (DragonFlyBSD only)
SIGCKPTEXIT (DragonFlyBSD only)
WEXITED
WSTOPPED
WNOWAIT
P_ALL
P_PID
P_PGID
P_PIDFD (Linux only)
P_UID (NetBSD/FreeBSD only)
P_GID (NetBSD/FreeBSD only)
P_SID (NetBSD/FreeBSD only)
P_JAILID (FreeBSD only)
PGSQL_TUPLES_CHUNK
POSIX_SC_CHILD_MAX
POSIX_SC_CLK_TCK
SO_EXCLUSIVEADDRUSE (Windows only)
SOCK_CONN_DGRAM (NetBSD only)
SOCK_DCCP (NetBSD only)
TCP_SYNCNT (Linux only)
SO_EXCLBIND (Solaris/Illumos only)
SO_NOSIGPIPE (macOs and FreeBSD)
SO_LINGER_SEC (macOs only)
IP_PORTRANGE (FreeBSD/NetBSD/OpenBSD only)
IP_PORTRANGE_DEFAULT (FreeBSD/NetBSD/OpenBSD only)
IP_PORTRANGE_HIGH (FreeBSD/NetBSD/OpenBSD only)
IP_PORTRANGE_LOW (FreeBSD/NetBSD/OpenBSD only)
SOCK_NONBLOCK
SOCK_CLOEXEC
SO_BINDTOIFINDEX
SODIUM_CRYPTO_AEAD_AEGIS128L_KEYBYTES
SODIUM_CRYPTO_AEAD_AEGIS128L_NSECBYTES
SODIUM_CRYPTO_AEAD_AEGIS128L_NPUBBYTES
SODIUM_CRYPTO_AEAD_AEGIS128L_ABYTES
SODIUM_CRYPTO_AEAD_AEGIS256_KEYBYTES
SODIUM_CRYPTO_AEAD_AEGIS256_NSECBYTES
SODIUM_CRYPTO_AEAD_AEGIS256_NPUBBYTES
SODIUM_CRYPTO_AEAD_AEGIS256_ABYTES
XML_OPTION_PARSE_HUGE

# Windows Support

Windowsサポートについて。

### Building with Visual Studio now requires at least Visual Studio 2019

Windowsでのビルドには、Visual Studio 2019以上が必要です。
Visual Studio 2022以上が推奨されています。


### AVX(2) CPU support is now properly detected for MSVC builds.

CPU拡張命令AVX・AVX2のサポートを適切に検出できるようになりました。

### Native AVX-512 builds are now supported

CPU命令セットAVX-512がサポートされました。
コンパイルオプション`--enable-native-intrinsics=avx512`で有効化されます。


# Other Changes

その他の変更。

## Closure names have been adjusted to include the parent function's name and the line of definition

クロージャにファイル名や定義行が含まれるようになりました。

```php
$c = function(){return 1;};
var_dump($c);

// PHP8.4 object(Closure)#1 (3) { "name"=>"path/to/file:10", "file"=>"path/to/file", "line"=>10 }
// PHP8.3 object(Closure)#1 (0) {}
```

これによってデバッグやスタックトレースの確認がやりやすくなります。

## run-tests.php now skips online tests by default

`run-tests.php`はオンラインテストをスキップするようになりました。

そもそも`run-tests.php`って何かというと[PHPに用意されているテストランナー](https://zenn.dev/hgsgtk/articles/fb9af8bfc64ec37bce2d#5.-%E3%83%86%E3%82%B9%E3%83%88%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B)です。
環境変数SKIP_ONLINE_TESTSを0にするとオンラインテストも実行されます。

## Fiber switching during destructor execution is now allowed

デストラクタ中でFiberの切り替えが可能になりました。
これまではできませんでした。

![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26088/4ba2e2f6-8c19-b11c-671c-42ceb45eaad2.png)

# Performance Improvements

パフォーマンスの改善。

## BCMath

### Improved performance of number conversions and operations

数値変換、演算のパフォーマンスが向上しました。

[除算が10倍速くなった](https://qiita.com/SakiTakamachi/items/8510ff59b09592ceb51d#bcmath-is-very-slow)など、相当な高速化がなされたようです。

## Core

### Improved the performance of floating point number parsing and formatting in ZTS builds under highly concurrent loads

スレッドセーフ実装であるZTSビルドにおいて、浮動小数点のパフォーマンスが向上しました。
`serialize()`や`serialize()`等に効果があります。

私はいつも[VS17 x64 Thread Safe](https://windows.php.net/download/)つまりZTSのバージョンをダウンロードしているのですが、正直[ZTSとNTSがどう違うのかわかりません](https://qiita.com/hnw/items/de83634fe39574b76ba1)。

### `sprintf()` using only `%s` and `%d` will be compiled into the equivalent string interpolation

`%s`と`%d`しか使っていない`sprintf()`は関数呼び出しが不要な形にコンパイルされます。
これによって関数呼び出しのオーバーヘッドがなくなります。

## DOM

### The performance of DOMNode::C14N() is greatly improved for the case without an xpath query

XPathクエリがない場合、[DOMNode::C14N()](https://www.php.net/manual/ja/domnode.c14n.php)のパフォーマンスが2桁上昇します。
2桁ってどんだけだよ。

### Improved performance and reduce memory consumption of XML serialization.

XMLシリアル化のメモリ消費量が削減され、パフォーマンスも向上しました。

### Reduced memory usage of node classes

Nodeクラスのメモリ使用量を削減しました。

## FTP

### Improved the performance of FTP uploads up to a factor of 10x for large uploads

大容量ファイルをFTPアップロードする際のパフォーマンスが、最大10倍ほど向上しました。

## Hash

### Added SSE2 and SHA-NI implementations of SHA-256

SHA-256について、SSE2とSHA-NIを実装しました。
SSE2対応CPUであれば1.3倍、SHA-NI対応CPUであれば3から5倍高速化します。

## MBString

### mb_strcut() is much faster now for UTF-8 and UTF-16 strings

UTF-8およびUTF-16文字列の`mb_strcut()`が大幅に高速化されました。

### Looking up mbstring encoding names is much faster now

マルチバイト文字のエンコーディング名検索が大幅に高速化されました。

### The performance of converting SJIS-win to unicode is greatly improved

`SJIS-win`からUnicodeへの変換性能が大幅に向上しました。

## MySQLnd

### Improved the performance of MySQLnd quoting

MySQLndのquoting性能が向上しました。

quotingってなに？
まさか[mysqli::real_escape_string()](https://www.php.net/manual/ja/mysqli.real-escape-string.php)のこと…ではないよねえ？


## PCRE

### Improved the performance of named capture groups

[名前付きキャプチャグループ](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Regular_expressions/Named_capturing_group)のパフォーマンスが向上しました。

## Random

### Improved the performance of \Random\Randomizer, with a specific focus on the getBytes() and getBytesFromString() methods


[\Random\Randomizer](https://www.php.net/manual/ja/class.random-randomizer.php)のパフォーマンスが向上しました。
特によく使われるであろう[Random\Randomizer::getBytes()](https://www.php.net/manual/ja/random-randomizer.getbytes.php)・[Random\Randomizer::getBytesFromString()](https://www.php.net/manual/ja/random-randomizer.getbytesfromstring.php)を重点的に改善しています。

## SimpleXML

### Improved performance and reduce memory consumption of XML serialization

XMLシリアル化のメモリ消費量が削減され、パフォーマンスも向上しました。

たぶん中身がDOMと同じなんじゃないかな。

## Standard

### Improved the performance of strpbrk()

[strpbrk()](https://www.php.net/manual/ja/function.strpbrk.php)のパフォーマンスが向上しました。

`strpos`しか使ったことないわ。

### The performance of strspn() and strcspn() is greatly improved

[strspn()](https://www.php.net/manual/ja/function.strspn.php)・[strcspn()](https://www.php.net/manual/ja/function.strcspn.php)のパフォーマンスが大幅に向上しました。

これまでO(n^2)だったのがO(n)になりました。

### get_browser() is much faster now, up to 1.5x - 2.5x for some test cases.

[get_browser()](https://www.php.net/manual/ja/function.get-browser.php)のパフォーマンスが向上しました。

1.5から2.5倍くらいになりました。


# 感想

長い。

相変わらずものすごい数の変更・改善が入っています。
これを毎年、[マイナーバージョンのバグ修正](https://www.php.net/releases/)もしっかりこなしながら出してくるのだから恐れ入りますね。

PHP8.4の目玉は、なんといってもやはり[プロパティフック](https://qiita.com/rana_kualu/items/06d68549058966a34c2b)と[非対称可視性](https://qiita.com/rana_kualu/items/c19e8efeb7561165fa64)でしょう。
PHP7あたりからどんどん追加されてきたこれらの機能によって、PHPはもはや下手な言語よりがっちりと型安全性を意識したコーディングが可能になります。
もちろん動的言語の限界はあるのでがんばればどうにかできないこともないですが、余計なことをせずVSCode+PHP Intelephense+Laravelあたりで普通に使っている限りでは、もう静的言語並みに型安全に書けます。
いやーかつてのPHP5時代とは本当に天地の差がありますよ。

さらに[mbstringに便利機能が増えた](https://qiita.com/rana_kualu/items/87bc5dd0396103bd7a32)り[配列検索がやりやすくなった](https://qiita.com/rana_kualu/items/6acf9064a55d7f50b4b8)り[newの括弧が不要になった](https://qiita.com/rana_kualu/items/5f34ced66558a4f94a4b)といった地道な改善もたくさん行われています。

また、PHP8.3から互換性のない変更はほとんどありません。
[下位互換性のない変更点](https://www.php.net/manual/ja/migration84.incompatible.php)を見るかぎりではわりとあるように見えますが、はっきりいって普通の使い方をしている限りではほぼ遭遇しないものばかりです。

ということで、さらに使いやすく便利で高性能になったPHP8.4、是非導入して使ってみましょう。