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

[PHP8.2](https://qiita.com/rana_kualu/items/64bd73ad3d314a1cccdc) / [PHP8.1](https://qiita.com/rana_kualu/items/e350b8ff80f929626eb9) / [PHP8.0](https://qiita.com/rana_kualu/items/c110cb244c3ee38c6859)


2021/11/26にPHP8.1.0が[リリースされました](https://www.php.net/)。
大きな新機能については、PHP8.0以降公開されるようになった[ランディングページ](https://www.php.net/releases/8.1/en.php)で見ることができます。

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


# Backward Incompatible Changes

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

## PHPコア

### Access to the $GLOBALS array is now subject to a number of restrictions

[`$GLOBALS`の内部処理を変更](https://qiita.com/rana_kualu/items/a6601b49e0591eb42200#restrict-globals-usage)します。

```php
$a = 1;
$globals = $GLOBALS; // 値をコピー
$globals['a'] = 2;
var_dump($a);

// PHP8.1
int(1)

// PHP8.0
int(2)
```

`$GLOBALS`は値をコピーしただけのはずなのにリファレンスになったりといった特殊な仕様がありました。
このせいで内部構造が複雑になり、パフォーマンスも劣化していました。
PHP8.1では、`$GLOBALS`を普通の変数と同じように扱うようにします。


### Passing null to a non-nullable argument of a built-in function is deprecated

[内部関数へのnullの引き渡し](https://qiita.com/rana_kualu/items/a6601b49e0591eb42200#deprecate-passing-null-to-non-nullable-arguments-of-internal-functions)に関するルール変更です。

```php
strlen(null);

// PHP8.1
Deprecated: strlen(): Passing null to parameter #1 ($string) of type string is deprecated

// PHP8.0
エラー出ない
```

[strlen](https://www.php.net/manual/ja/function.strlen)の引数は`string`ですが、これまではnullを渡しても何もエラーが出ませんでした。
PHPは元々型に緩かったという経緯もあり、内部関数への引数には甘めの判定をしていました。
それを徐々に厳しくしていく変更です。
PHP9ではユーザ定義関数と同様、TypeErrorになる予定です。


### inherited method will now share static variables with the parent method.

[静的変数の継承時の挙動変更](https://qiita.com/rana_kualu/items/e65844540581952e73ff)です。

```php
class A{
    public static function counter(){
        static $counter = 0;
        $counter++;
        return $counter;
    }
}

class B extends A{}

var_dump(A::counter()); // int(1)
var_dump(A::counter()); // int(2)
var_dump(B::counter()); // int(3) PHP8.0までint(1)
var_dump(B::counter()); // int(4) PHP8.0までint(1)
```

何故かこれまで、静的変数は継承したときに別の変数になっていたのですが、今後は同じになります。
変更後はクラス変数と同じ挙動です。

### Most non-final internal methods now require overriding methods to declare a  compatible return type

ビルトインクラスの[返り値の型の厳格化](https://qiita.com/rana_kualu/items/a6601b49e0591eb42200#add-return-type-declarations-for-internal-methods)です。

```php
class MyDateTime extends DateTime{
    public function modify(string $modifier):int{
        return 1;
    }
}

$dt = new MyDateTime();
$dt->modify('modifier');

// PHP8.1
Deprecated:  Return type of MyDateTime::modify(string $modifier): int should either be compatible with DateTime::modify(string $modifier): DateTime|false

// PHP8.0
エラー出ない

```

`DateTime::modify()`の返り値は`DateTime|false`ですが、extends時に別の型を指定しても動作していました。
これが禁止されます。
ユーザ定義クラスでは最初からFatal Errorですが、ビルトインクラスは互換性のため特別に緩くしてありました。
今後は徐々にユーザ定義クラスと揃えていくということです。

互換性などの問題で今後も異なる返り値を使い続けたい場合は、アトリビュート`#[ReturnTypeWillChange]`で黙らせることができます。


## Fileinfo

### The fileinfo functions now accept and return, respectively, finfo objects instead of resources

[finfo_open](https://www.php.net/manual/ja/ref.fileinfo.php)などの関数は、これまでリソースを返していたのがfinfoオブジェクトを返すようになりました。

```php
var_dump(finfo_open(FILEINFO_NONE));

// PHP8.1
object(finfo)#1 (0) {}

// PHP8.0
resource(4) of type (file_info)
```

他の[Fileinfo関数](https://www.php.net/manual/ja/ref.fileinfo.php)はこれまでと同じ書き方で透過的に動作します。

[is_resource](https://www.php.net/manual/ja/function.is-resource)でチェックしている場合は修正が必要です。


## FTP

### The FTP functions now accept and return, respectively, FTP\Connection objects instead of resources

[ftp_connect](https://www.php.net/manual/ja/function.ftp-connect.php)などの関数は、これまでリソースを返していたのが`FTP\Connection`オブジェクトを返すようになりました。
他の[FTP関数](https://www.php.net/manual/ja/ref.ftp.php)はこれまでと同じ書き方で透過的に動作します。

## IMAP

### The IMAP functions now accept and return, respectively, IMAP\Connection objects instead of resources

[imap_open](https://www.php.net/manual/ja/function.imap-open.php)などの関数は、これまでリソースを返していたのが`IMAP\Connection`オブジェクトを返すようになりました。
他の[IMAP関数](https://www.php.net/manual/ja/ref.imap.php)はこれまでと同じ書き方で透過的に動作します。

## LDAP

### The LDAP functions now accept and return, respectively, LDAP\Connection objects instead of "ldap link" resources

[ldap_connect](https://www.php.net/manual/ja/function.ldap-connect.php)などの関数は、これまでリソースを返していたのが`LDAP\Connection`オブジェクトを返すようになりました。
他の[LDAP関数](https://www.php.net/manual/ja/ref.ldap.php)はこれまでと同じ書き方で透過的に動作します。

### The LDAP functions now accept and return, respectively, LDAP\Result objects instead of "ldap result" resources

[ldap_list](https://www.php.net/manual/ja/function.ldap-list.php)などの関数は、これまでリソースを返していたのが`LDAP\Result`オブジェクトを返すようになりました。
他の[LDAP関数](https://www.php.net/manual/ja/ref.ldap.php)はこれまでと同じ書き方で透過的に動作します。

### The LDAP functions now accept and return, respectively, LDAP\ResultEntry objects instead of "ldap result entry" resources

[ldap_first_entry](https://www.php.net/manual/ja/function.ldap-first-entry.php)などの関数は、これまでリソースを返していたのが`LDAP\ResultEntry`オブジェクトを返すようになりました。
他の[LDAP関数](https://www.php.net/manual/ja/ref.ldap.php)はこれまでと同じ書き方で透過的に動作します。


## MySQLi

### mysqli_fetch_fields() and mysqli_fetch_field_direct() will now always return zero for max_length.

[mysqli_fetch_fields](https://www.php.net/manual/ja/mysqli-result.fetch-fields.php)および[mysqli_fetch_field_direct](https://www.php.net/manual/ja/mysqli-result.fetch-field-direct.php)の返り値のうち、`max_length`は常に0になります。
そもそも`結果セットにおけるフィールドの最大幅`って何だ。

### The MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH option no longer has an effect.

定数[MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH](https://www.php.net/manual/ja/mysqli.constants.php)は何の意味も持たなくなりました。

### The MYSQLI_STORE_RESULT_COPY_DATA option no longer has an effect.

定数[MYSQLI_STORE_RESULT_COPY_DATA](https://www.php.net/manual/ja/mysqli.store-result.php)は何の意味も持たなくなりました。

### The default error handling mode has been changed from "silent" to "exceptions".

mysqliの[エラーモードのデフォルトがException](https://qiita.com/rana_kualu/items/a6601b49e0591eb42200#change-default-mysqli-error-mode)になりました。


### Classes extending mysqli_stmt::execute() will be required to specify the additional parameter now.

[mysqli_stmt::execute](https://www.php.net/manual/ja/mysqli-stmt.execute)に[実行時引数引き渡し](https://qiita.com/rana_kualu/items/a6601b49e0591eb42200#mysqli-bind-in-execute)ができるようになりました。

```php
// mysqli 事前渡し
$stmt = $mysqli->prepare('INSERT INTO users(id, name) VALUES(?,?)');
$stmt->bind_param('ss', $id, $name);
$stmt->execute();

// mysqli 実行時渡し
$stmt = $mysqli->prepare('INSERT INTO users(id, name) VALUES(?,?)');
$stmt->execute([$id, $name]);
```

[PDOStatement::execute()](https://www.php.net/manual/ja/pdo.exec)と同じ使い方ができるようになります。

### mysqli::connect() will now return true instead of null on success.

[mysqli::connect()](https://www.php.net/manual/ja/mysqli.construct.php)は成功時にtrueを返すようになりました。
これまでは何故かnullでした。


## MySQLnd

### The mysqlnd.fetch_data_copy ini setting has been removed.

ini設定[mysqlnd.fetch_data_copy](https://www.php.net/manual/ja/mysqlnd.config.php#ini.mysqlnd.fetch_data_copy)が削除されました。
ただしユーザから見える挙動に変化はありません。

## OpenSSL

### EC private keys will now be exported in PKCS#8 format

ECの秘密鍵が、他の鍵と同じくPKCS#8形式でエクスポートされるようになりました。

### openssl_pkcs7_encrypt() and openssl_cms_encrypt() will now default to using AES-128-CBC

[openssl_pkcs7_encrypt](https://www.php.net/manual/ja/function.openssl-pkcs7-encrypt.php)と[openssl_cms_encrypt](https://www.php.net/manual/ja/function.openssl-cms-encrypt.php)の暗号化アルゴリズムのデフォルト値がAES-128-CBCになりました。
これまではRC2-40でしたが、これは脆弱なのでOpenSSL3.0ではデフォルトでは無効化されています。

## PDO

### PDO::ATTR_STRINGIFY_FETCHES now also stringifies values of type bool to "0" or "1".

PDOの設定[PDO::ATTR_STRINGIFY_FETCHES](https://www.php.net/manual/ja/pdo.setattribute.php)は、bool値を"0"か"1"にするようになりました。
これまではbool値は変換しませんでした。

### Calling bindColumn() with PDO::PARAM_LOB will now consistently bind a stream result

[PDOStatement::bindColumn()](https://www.php.net/manual/ja/pdostatement.bindcolumn)の引数に型[PDO::PARAM_LOB](https://www.php.net/manual/ja/pdo.lobs.php)を渡すと、データが必ずストリームに入ってくるようになりました。
これまではデータベースドライバ等によってストリームだったり文字列だったりすることがありました。


## PDO MySQL

### Integers and floats in result sets will now be returned using native PHP types when using emulated prepared statements.

プリペアドステートメントを使った場合、返ってきたint型・float型の結果はPHPのint型・float型になりました。
これまではMySQL側の型に関わらず返り値は常に文字列型でした。

## PDO SQLite

### Integers and floats in results sets will now be returned using native PHP types.

返ってきたint型・float型の結果はPHPのint型・float型になりました。

## PgSQL

### The PgSQL functions now accept and return, respectively, \PgSql\Connection objects instead of "pgsql link" resources.

[pg_connect](https://www.php.net/manual/ja/function.pg-connect.php)などの関数は、これまでリソースを返していたのが`PgSql\Connection`オブジェクトを返すようになりました。

### The PgSQL functions now accept and return, respectively, \PgSql\Result objects instead of "pgsql result" resources.

[pg_query](https://www.php.net/manual/ja/function.pg-query.php)などの関数は、これまでリソースを返していたのが`PgSql\Result`オブジェクトを返すようになりました。

### The PgSQL functions now accept and return, respectively, \PgSql\Lob objects instead of "pgsql large object" resources.

[pg_lo_open](https://www.php.net/manual/ja/function.pg-lo-open.php)などの関数は、これまでリソースを返していたのが`PgSql\Lob`オブジェクトを返すようになりました。


## Phar

### To comply with the ArrayAccess interface, Phar::offsetUnset() and PharData::offsetUnset() no longer return a boolean.

[Phar::offsetUnset()](https://www.php.net/manual/ja/phar.offsetunset.php)および[PharData::offsetUnset()](https://www.php.net/manual/ja/phardata.offsetunset.php)は、これまでtrue/falseを返していたのが値を返さなくなりました。
オーバーライドしている[https://www.php.net/manual/ja/class.arrayaccess.php](https://www.php.net/manual/ja/class.arrayaccess.php)に揃えたものです。

```php
$p = new Phar('./my.phar');
var_dump($p->offsetUnset('a'));

// PHP8.1
NULL

// PHP8.0
true
```

## PSpell

### The PSpell functions now accept and return, respectively, PSpell\Dictionary objects instead of "pspell" resources.

[pspell_new](https://www.php.net/manual/ja/function.pspell-new.php)などの関数は、これまでリソースを返していたのが`PSpell\Dictionary`オブジェクトを返すようになりました。

### The PSpell functions now accept and return, respectively, PSpell\Config objects instead of "pspell config" resources.

[pspell_new_config](https://www.php.net/manual/ja/function.pspell-config-create.php)などの関数は、これまでリソースを返していたのが`PSpell\Config`オブジェクトを返すようになりました。

## Standard

### version_compare() no longer accepts undocumented operator abbreviations.

[version_compare](https://www.php.net/manual/ja/function.version-compare)関数は、これまで第三引数の比較演算子に非公式な引数`!`、`l`・`g`などを受け付けていたのですが、これが禁止されました。
これはドキュメント化されておらず、ユーザノートにも記載はなく、そもそも知ってる人が何人いたのだろうというレベルの謎機能です。

```php
var_dump(version_compare(PHP_VERSION, '8.1.0rc5', 'l'));

// PHP8.1
PHP Fatal error:  Uncaught ValueError: version_compare(): Argument #3 ($operator) must be a valid comparison operator

// PHP8.0
true
```

今後は`l`ではなく`lt`もしくは`<`と記載しなければなりません。
しかし、これが実際に影響する人は存在するのでしょうか。


### htmlspecialchars(), htmlentities(), htmlspecialchars_decode(), html_entity_decode() and get_html_translation_table() now use ENT_QUOTES | ENT_SUBSTITUTE rather than ENT_COMPAT by default. 

[htmlspecialchars()](https://www.php.net/manual/ja/function.htmlspecialchars)をはじめとした各関数の、変換フラグのデフォルト値が`ENT_QUOTES | ENT_SUBSTITUTE`になりました。
これまでのデフォルト値は`ENT_COMPAT`であり、シングルクォートは変換されませんでした。

```php
var_dump(htmlspecialchars('a"b\'c'));

// PHP8.1
a&quot;b&#039;c

// PHP8.0
a&quot;b'c
```

これまでの初期値がおかしかった案件。


### debug_zval_dump() will now print reference wrappers with their refcount, instead of only prepending a "&" to the value.

[debug_zval_dump()](https://www.php.net/manual/ja/function.debug-zval-dump)は、参照値に参照カウントを表示するようになりました。

```php
<?php
$r = 1;
$a = [&$r];
debug_zval_dump($a);

// PHP8.1
array(1) refcount(2){
  [0]=>
  reference refcount(2) {
    int(1)
  }
}

// PHP8.0
array(1) refcount(2){
  [0]=>
  &int(1)
}
```

細かすぎてわからない変更。


### debug_zval_dump() will now print "interned" instead of a dummy refcount of one for interned strings and immutable arrays.

[debug_zval_dump()](https://www.php.net/manual/ja/function.debug-zval-dump)は、参照カウントが不要なところでは`interned`を表示するようになりました。

```php
$a = "string";
debug_zval_dump($a);

// PHP8.1
string(6) "string" interned

// PHP8.0
string(6) "string" refcount(1)
```

これまで表示されていたのが謎です。


## SPL

### SplFixedArray will now be JSON encoded like an array.

[SplFixedArray](https://www.php.net/manual/ja/splfixedarray.construct)のJSONエンコード方式が配列と同じになりました。

```php
var_dump(json_encode([1, 2]));
var_dump(json_encode(SplFixedArray::fromArray([1, 2])));

// PHP8.1
"[1]", "[1]"

// PHP8.0
"[1]", "{"0":1}"
```

これまで異なっていたのが謎。


# New Features

新機能。

## Core

### It is now possible to specify octal integer by using the explicit "0o"/"0O" prefix

8進数を接頭辞`0o`で表現できるようになりました。

```php
var_dump(0o10);

// PHP8.1
int(8)

// PHP8.0
Parse error: syntax error, unexpected identifier "o10"
```

これまで8進数だけ`010`という謎形式だったものを[2進数・16進数と合わせた](https://qiita.com/rana_kualu/items/2663f4b9bf8aefcc3955)ものです。
既存の形式も当面の間は有効であり、非推奨になる予定はありません。

### Added support for array unpacking with strings keys

[文字列キーの配列をアンパック](https://qiita.com/rana_kualu/items/a6601b49e0591eb42200#array-unpacking-with-string-keys)できるようになります。

```php
var_dump([...['a'=>1], ...['a'=>2]]);

// PHP8.1
['a'=>2]

// PHP8.0
Fatal error: Cannot unpack array with string keys
```

### Added support for enumerations.

[列挙型](https://qiita.com/rana_kualu/items/bdfa6c844125c1d0f4d4)が追加されました。

```php
enum Suit : string{
    case Hearts = 'H';
    case Diamonds = 'D';
    case Clubs = 'C';
    case Spades = 'S';
}

var_dump(Suit::Diamonds, Suit::Diamonds->name, Suit::Diamonds->value); // enum(Suit::Diamonds), "Diamonds", "D"
```

個別にメソッドを実装したりも可能で、様々な遊び甲斐がありそうな機能です。

### Added support for never return type

[never型](https://qiita.com/rana_kualu/items/134e65951c05de014165)が追加されました。

```php
function foo():never{
    exit;
}
```

常にexitしたり常に例外を吐くような、呼び出し元に帰らない型です。

### Added support for fibers.

[Fiber](https://qiita.com/rana_kualu/items/6247441f6fdd63c10a06)が追加されました。
PHPのユーザサイドで非同期処理を書けるようになる画期的な機能です。

```php
$fiber = new Fiber(function (): void {
    $value = Fiber::suspend('fiber');
    echo "レジュームした。$value: ", $value, "\n";
});

$value = $fiber->start();

echo "一時停止した。$value: ", $value, "\n";

$fiber->resume('test');
```

とはいえPHPでの実装は最低限必要な機能に抑えられているため、実際に使いこなすにはライブラリの登場を待ったほうがいいかもしれません。

### It is now possible to use "new ClassName()" expressions as parameter default values

[引数デフォルト値でnew](https://qiita.com/rana_kualu/items/e44235c21539d0a411b0)できるようになります。

```php
class Test {
    public function __construct(
        private Logger $logger = new NullLogger,
    ) {}
}
```

これまではいったんnullなどで受け取ってから、nullであればnewするといった一手間が必要でした。

また、これは[RFC](https://wiki.php.net/rfc/new_in_initializers)には全く書かれていないのですが、[define](https://www.php.net/manual/ja/function.define)にオブジェクトを渡せるようになりました。

```php
define('HOGE', new stdClass());

// PHP8.1
エラー出ない

// PHP8.0
PHP Fatal error:  Uncaught TypeError: define(): Argument #2 ($value) cannot be an object, stdClass given
```

全く関係なさそうな話なのに[唐突にここに書かれている](https://www.php.net/manual/ja/migration81.new-features.php#migration81.new-features.core.new-in-initializer)のは、処理を共通で使っているから副作用でそうなったとかそんなかんじなのですかね。

###  Closures for callables can now be created using the syntax `myFunc(...)`,

[Closure::fromCallable](https://www.php.net/manual/ja/closure.fromcallable.php)の[糖衣構文](https://qiita.com/rana_kualu/items/a6601b49e0591eb42200#first-class-callable-syntax)です。

```php
// 同じ
myFunc(...);
Closure::fromCallable('myFunc');
```

前者と後者は全く同じ意味になります。
`...`は省略ではなくこのままの文字です。

### File uploads now provide an additional full_path key

ファイルのアップロード時に、`$_FILES['full_path']`が追加されました。
[webkitdirectory](https://developer.mozilla.org/ja/docs/Web/API/HTMLInputElement/webkitDirectory)でディレクトリごとアップロードした際に、[ディレクトリを取り出せる](https://qiita.com/akase244/items/f5f7287cfe28bebe00fc)ようにするものです。


### It is now allowed to specify named arguments after an argument unpack

引数アンパックの後ろに名前付き引数を追加することができるようになりました。

```php
foo(...[1], named: "str");

function foo(...$args){
    var_dump($args); // [1, "named"=>"str"]
}
```

これまでは引数アンパックと名前付き引数を組み合わせることはできませんでした。

逆の`foo(named: $arg, ...$args);`はPHP8.1でもエラーになります。


### Added support for intersection types.

[交差型](https://qiita.com/rana_kualu/items/f49582bc94e0bae23d9c)が追加されました。

```php
function foo(Traversable&Countable $arg){ }

foo(new ArrayIterator()); // エラー出ない
foo(new DirectoryIterator('.')); // Fatal error: Uncaught TypeError: foo(): Argument #1 ($arg) must be of type Traversable&Countable, DirectoryIterator given
```

型のANDです。
`Traversable&Countable`であれば、TraversableかつCountableの型しか受け付けません。


### Added support for the final modifier for class constants.

[finalクラス定数](https://qiita.com/rana_kualu/items/db6e93beca61ce9eeea7)が追加されました。

```php
class FOO{
    final public const HOGE = 1;
}

class BAR extends FOO{
    public const HOGE = 2;
}

// Fatal error: BAR::HOGE cannot override final constant FOO::HOGE
```

`final`のついたクラス定数は上書きできなくなります。


### Added support for readonly properties.

[readonlyアクセス修飾子](https://qiita.com/rana_kualu/items/ae96400a0a6981eca64a)が追加されました。

```php
class Test {
    public readonly string $name;
    
    public function setName(string $name) {
        $this->name = $name;
    }
}

$t = new Test();
$t->setName('a'); // OK
$t->setName('b'); // Fatal error: Uncaught Error: Cannot modify readonly property Test::$name


$t = new Test();
$t->name = 'a'; // Fatal error: Uncaught Error: Cannot initialize readonly property Test::$name from global scope
```

内部からは一回だけ書き込み可能ですが、一度書き込んだら上書きはできません。
外部からは一切書き込み不可能です。

極めてよくある『読まれてもいいけど書き込ませたくない』という要望へのソリューションです。

## Curl

### Added CURLOPT_DOH_URL option.

定数[CURLOPT_DOH_URL](https://www.php.net/manual/ja/curl.constants.php)が追加されました。

[libcurl](https://curl.se/libcurl/c/CURLOPT_DOH_URL.html)のラッパーです。
[DNS over HTTPS](https://ja.wikipedia.org/wiki/DNS_over_HTTPS)に対応したDNSサーバのURLを指定します。
これで何がうれしいかというと、DNSの中間者攻撃を防ぐことができます。

### Added certificate blob options when for libcurl >= 7.71.0

定数CURLOPT_ISSUERCERT_BLOB・CURLOPT_PROXY_ISSUERCERT・CURLOPT_PROXY_ISSUERCERT_BLOB・CURLOPT_PROXY_SSLCERT_BLOB・CURLOPT_PROXY_SSLKEY_BLOB・CURLOPT_SSLCERT_BLOB・CURLOPT_SSLKEY_BLOBが追加されました。

これらもlibcurlに追加された定数のラッパーです。

### Added CURLStringFile, which can be used to post a file from a string rather than a file

ファイルのアップロード用に[CURLStringFile](https://www.php.net/manual/ja/class.curlstringfile.php)クラスが追加されました。

既存の[CURLFile](https://www.php.net/manual/ja/class.curlfile.php)はファイルの実体を指定する必要があって面倒だったのですが、CURLStringFileは文字列を直接ファイルとしてアップロードできます。

```php
$file = new CURLStringFile($data, 'filename.txt', 'text/plain');
curl_setopt($curl, CURLOPT_POSTFIELDS, ['file' => $file]);
```

中身が`$data`のファイルが、`filename.txt`という名前でアップロードされます。

## FPM

### Added openmetrics status format.

openmetricsフォーマットが追加されました。

[Prometheus](https://prometheus.io/)がFPMの情報を取得するのに使えるらしいですが、なんのことだかよくわからない。

### Added new pool option for the dynamic process manager called pm.max_spawn_rate.

プールオプションpm.max_spawn_rateが追加されました。

Apacheのpreforkみたいな話ですかね？
そもそも[FPM](https://github.com/php/php-src/blob/php-8.1.0/sapi/fpm/fpm/fpm_conf.c)ってなんなんだ。

## GD

### Avif support is now available through the imagecreatefromavif() and imageavif() functions

関数[imagecreatefromavif()](https://www.php.net/manual/ja/function.imagecreatefromavif)および[imageavif()](https://www.php.net/manual/ja/function.imageavif)が追加されました。

[Avifフォーマット](https://lpeg.info/webworks/image_avif.html)が使えるようになります。
WebPより低容量高画質だそうです。

正直いまだにpng使ってる。


## hash

### The following functions have changed signatures, to support an optional `$options` argument

3関数[hash](https://www.php.net/manual/ja/function.hash)、[hash_file](https://www.php.net/manual/ja/function.hash-file)、[hash_init](https://www.php.net/manual/ja/function.hash-init)に第四引数`array $options=[]`が追加されました。

アルゴリズムに特有のオプションを渡せるようになります。

### Added MurmurHash3 with streaming support.

ハッシュアルゴリズム[MurmurHash3](https://en.wikipedia.org/wiki/MurmurHash)が追加されました。

```php
$h = hash("murmur3f", 'hoge', options: ["seed" => 42]);
var_dump($h); // "231990405db0441823f7f90ce310315d"
```

実装されたのは`murmur3a`・`murmur3c`・`murmur3f`の3種類です。
MurmurHash3は引数にシード値を渡せるため、第四引数`$options`が必要となりました。


### Added xxHash.

ハッシュアルゴリズム[xxHash](https://github.com/Cyan4973/xxHash)が追加されました。

```php
$h = hash("xxh128", 'hoge', options: ["secret"=>"secret値は136バイト以上の長さが必要".str_repeat('a',100)]);
var_dump($h); // "d5ace21ffc307b3ae0737e70c0e7525e"
```

実装されたのは`xxh32`・`xxh64`・`xxh3`・`xxh128`の4種類です。
引数にシード値もしくはシークレット文字列を渡すことができます。

## MySQLi

###  mysqli.local_infile_directory ini setting has been added

ini設定[mysqli.local_infile_directory](https://www.php.net/manual/ja/mysqli.configuration.php#ini.mysqli.local-infile-directory)が追加されました。

マニュアルには`LOCAL DATA`って書いてあるのですがそんなSQLは無いので、おそらく[LOAD DATA LOCAL](https://dev.mysql.com/doc/refman/ja/load-data.html)のことだと思います。
`LOAD DATA LOCAL`で読み込み可能なディレクトリを制限します。

### Binding in execute has been added to mysqli prepared statements.

[mysqli_stmt::execute](https://www.php.net/manual/ja/mysqli-stmt.execute.php)が[実行時バインド](https://qiita.com/rana_kualu/items/a6601b49e0591eb42200#mysqli-bind-in-execute)できるようになりました。

```php
// 何故か今までできなかった
$stmt = $mysqli->prepare('INSERT INTO users(id, name) VALUES(?,?)');
$stmt->execute([$id, $name]);

// PDOは今までもできた
$stmt = $pdo->prepare('INSERT INTO users(id, name) VALUES(?,?)');
$stmt->execute([$id, $name]);
```

PDOと動作を合わせたものとなります。

### A new method has been added to mysqli_result called mysqli_fetch_column().

メソッド[mysqli_fetch_column](https://www.php.net/manual/ja/mysqli-result.fetch-column.php)が追加されました。

[PDOStatement::fetchColumn](https://www.php.net/manual/ja/pdostatement.fetchcolumn.php)に相当するものです。
正直使いどころがわからない。

## PDO MySQL

### The PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY attribute has been added

定数[PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY](https://www.php.net/manual/ja/ref.pdo-mysql.php)が追加されました。

`mysqli.local_infile_directory`と同じものです。

## PDO SQLite

### SQLite's "file:" DSN syntax is now supported

DSN構文`file`がサポートされました。

```php
new PDO('sqlite:file:path/to/sqlite.db?mode=ro')
```

元々は`sqlite:path/to/sqlite.db?mode=ro`ってかんじで指定していたはずなので、ファイルを明記できるようになった？

## Posix

### POSIX_RLIMIT_KQUEUES and POSIX_RLIMIT_NPTS.

[POSIX定数](https://www.php.net/manual/ja/posix.constants.setrlimit.php)POSIX_RLIMIT_KQUEUES、POSIX_RLIMIT_NPTSが追加されました。
FreeBSDでのみ定義されます。

## Standard

### fputcsv() now accepts a new "eol" argument 

[fputcsv()](https://www.php.net/manual/ja/function.fputcsv)に第6引数`string $eol = "\n"`が追加されました。
行末の改行を変更できます。

引数が多すぎるので`array $options`にしてほしい。

## SPL

### SplFileObject::fputcsv() now accepts a new "eol" argument 

[SplFileObject::fputcsv()](https://www.php.net/manual/ja/splfileobject.fputcsv.php)に第5引数`string $eol = "\n"`が追加されました。
関数`fputcsv()`と全く同じ変更です。


# Changes in SAPI modules

## CLI

コマンドラインの変更点。

### Using -a without the readline extension will now result in an error.

[readline](https://www.php.net/manual/ja/book.readline.php)拡張機能が有効でないときは、PHPの対話シェル`-a`がエラーになるようになりました。

これまでは`-a`を無視して通常モードのPHPが起動していました。

### Remote functionality from phpdbg has been removed

[phpdbg](https://www.php.net/manual/ja/intro.phpdbg.php)のリモート機能が削除されました。

とあるのですがなんのことだかわかりません。
`-a`とかがなくなったってことでいいのかな。


# Deprecated Functionality

非推奨になった機能・関数など。

## Core

###   . Implementing the Serializable interface without also implementing __serialize() and __unserialize() has been deprecated.

`Serializable`が[非推奨になりました](https://qiita.com/rana_kualu/items/a6601b49e0591eb42200#phasing-out-serializable)。

```php
class HOGE implements Serializable{
    public function serialize(){
        return serialize($this->data);
    }
    public function unserialize($data){
        $this->data = unserialize($data);
    }
}

// PHP8.1
Deprecated: HOGE implements the Serializable interface, which is deprecated. Implement __serialize() and __unserialize() instead (or in addition

// PHP8.0
エラー出ない
```

PHP7.4でマジックメソッド`__serialize/__unserialize`が実装されたため、今後はそちらが推奨されます。

### Implicit conversion of floats to integers that result in loss of precision is deprecated.

`float`から`int`への暗黙の型変換が[非推奨になりました](https://qiita.com/rana_kualu/items/a6601b49e0591eb42200#deprecate-implicit-non-integer-compatible-float-to-int-conversions)。

```php
function toInt(int ...$arg){ }
toInt(1.5);

// PHP8.1
Deprecated: Implicit conversion from float 1.5 to int loses precision

// PHP8.0
エラー出ない
```

1.5から1へと情報が抜け落ちてしまうためです。
`int`から`float`等への暗黙の型変換は、情報が抜け落ちないため今後もエラーは出ません。

また、明示的な変換については今後も問題なく可能です。

### Calling a static method or accessing a static property directly on a trait is deprecated.

traitのstaticプロパティへの直接アクセスが[非推奨になりました](https://qiita.com/rana_kualu/items/c894b2160d1f8799eed2#accessing-static-members-on-traits)。

```php
trait T{
    public static $foo = 1;
}
var_dump(T::$foo);

// PHP8.1
Deprecated:  Accessing static trait property T::$foo is deprecated

// PHP8.0
エラー出ない
```

### Returning a non-array from __sleep will raise a warning

マジックメソッド[__sleep](https://www.php.net/manual/ja/language.oop5.magic.php#object.sleep)が配列以外を返すとE_WARININGが発生するようになりました。

```php
class A{
    public function __sleep(){
        return 1;
    }
}

$a = new A;
serialize($a);

// PHP8.1
Warning: serialize(): A::__sleep() should return an array

// PHP8.0
Warning: serialize(): A::__sleep() should return an array
```

って書いてあるんだけど、実際はPHP8.0でもエラー出ます。
よくわからない。

### Returning by reference from a void function is deprecated.

返り値がvoidのメソッド・関数をリファレンスで書くことが[非推奨になりました](https://qiita.com/rana_kualu/items/c894b2160d1f8799eed2#return-by-reference-with-void-type)。

```php
function &ref():void{ }

// PHP8.1
Deprecated: Returning by reference from a void function is deprecated

// PHP8.0
エラー出ない
```

意味がない文法のため禁止されます。

### Automatic conversion of "false" into an empty array on write operands is deprecated.

falseから配列の自動生成が[非推奨になりました](https://qiita.com/rana_kualu/items/a6601b49e0591eb42200#deprecate-autovivification-on-false)。

```php
$a = false;
$a[] = 1;

// PHP8.1
Deprecated: Automatic conversion of false to array is deprecated

// PHP8.0
エラー出ない
```

元々voidやundefinedなど存在しないところからは生成可能、intやstring、true等の通常型からは生成不可能でした。
falseはtrueと揃えるべきだろうということで合わせたものとなります。

## Ctype

### Passing a non-string value to ctype_*() functions is deprecated.

[ctype関数](https://www.php.net/manual/ja/function.ctype-digit.php)の引数の型において、string型以外は[非推奨になりました](https://qiita.com/rana_kualu/items/c894b2160d1f8799eed2#ctype_-function-family-accepts-int-parameters)。

```php
var_dump(ctype_digit(128));

// PHP8.1
Deprecated: ctype_digit(): Argument of type int will be interpreted as string in the future

// PHP8.0
false
```

元々-128から255までのint型をASCII値として扱うというとんでもない罠仕様があったため、これを防ぐついでに意味のない入力を禁止します。

## Date

### The date_sunrise() and date_sunset() functions have been deprecated 

[date_sunrise](https://www.php.net/manual/ja/function.date-sunrise.php)と[date_sunset](https://www.php.net/manual/ja/function.date-sunset.php)が[非推奨になりました](https://qiita.com/rana_kualu/items/c894b2160d1f8799eed2#date_sunrise-and-date_sunset)。

[date_sun_info](https://www.php.net/manual/ja/function.date-sun-info.php)が完全上位互換なのでそちらを使いましょう。

### The strftime() and gmstrftime() functions have been deprecated

[strftime](https://www.php.net/manual/ja/function.strftime.php)と[gmstrftime](https://www.php.net/manual/ja/function.gmstrftime.php)が[非推奨になりました](https://qiita.com/rana_kualu/items/c894b2160d1f8799eed2#strftime-and-gmtstrftime)。

これらはプラットフォームによって出力がかわってしまうためです。
影響を受けない[DateTime::format()](https://www.php.net/manual/ja/datetime.format.php)などを使いましょう。

## Filter

### The FILTER_SANITIZE_STRING and FILTER_SANITIZE_STRIPPED filters have been deprecated.

定数FILTER_SANITIZE_STRING・FILTER_SANITIZE_STRIPPEDが[非推奨になりました](https://qiita.com/rana_kualu/items/c894b2160d1f8799eed2#filter_sanitize_string)。

一見[strip_tags](https://www.php.net/manual/ja/function.strip-tags.php)と同じように見えて異なる動作であり、何に対するサニタイズなのかも明白にされておらずわかりにくいため削除されます。

### The filter.default ini setting is deprecated.

ini設定`filter.default`が[非推奨になりました](https://qiita.com/rana_kualu/items/c894b2160d1f8799eed2#filterdefault-ini-setting)。

これは`$_REQUEST`等の入力値をフィルタリングする機能です。
マジッククォート以上に強力な機能であり、存在そのものが危険であるため封印されます。

## GD

###  The $num_points parameter of image(open|filled)polygon has been deprecated.

[imagepolygon](https://www.php.net/manual/ja/function.imagepolygon.php)などの引数`$num_points`が[非推奨になりました](https://qiita.com/rana_kualu/items/c894b2160d1f8799eed2#num_points-parameter-of-imageopenfilledpolygon)。

そもそもPHPで絵なんて描かないからわからぬ。

## Hash

### The mhash*() functions are deprecated.

[mhash](https://www.php.net/manual/ja/function.mhash.php)をはじめとした[mhash*関数](https://www.php.net/manual/ja/ref.mhash.php)が[非推奨になりました](https://qiita.com/rana_kualu/items/c894b2160d1f8799eed2#mhash-function-family)。

かわりに[hash*関数](https://www.php.net/manual/ja/ref.hash.php)を使いましょう。

## IMAP

### The NIL constant has been deprecated.

定数[NIL](https://www.php.net/manual/ja/imap.constants.php)が[非推奨になりました](https://qiita.com/rana_kualu/items/c894b2160d1f8799eed2#nil-constant-defined-by-the-imap-extension)。

NILといえばNULLと同じと思われがちですが、PHPではNILの値は`0`です。


## Intl

### Calling IntlCalendar::roll() with bool argument is deprecated.

[IntlCalendar::roll()](https://www.php.net/manual/ja/intlcalendar.roll.php)の第二引数`$value`の型boolが[非推奨になりました](https://qiita.com/rana_kualu/items/c894b2160d1f8799eed2#passing-bool-for-value-argument-of-intlcalendarroll)。

trueは1、falseは-1と、他の関数ではありえない使われ方をしていました。

## 

### Calling mb_check_encoding() without an argument is deprecated.

引数なしの[mb_check_encoding()](https://www.php.net/manual/ja/function.mb-check-encoding.php)が[非推奨になりました](https://qiita.com/rana_kualu/items/c894b2160d1f8799eed2#mb_check_encoding-without-argument)。

実はまともに実装されていませんでした。

## MySQLi

### The mysqli_driver::$driver_version property has been deprecated.

[mysqli_driver::$driver_version](https://www.php.net/manual/ja/class.mysqli-driver.php#mysqli-driver.props.driver-version)プロパティが非推奨になりました。

このプロパティは10年以上更新されておらず実質的に意味がありません。
かわりに[PHP_VERSION_ID](https://www.php.net/manual/ja/reserved.constants.php)が推奨されています。

### Calling mysqli::get_client_info in OO style or passing $mysqli argument to mysqli_get_client_info() function has been deprecated.

[mysqli::get_client_info](https://www.php.net/manual/ja/mysqli.get-client-info.php)の引数が非推奨になりました。

引数なしの`mysqli_get_client_info()`はクライアントのバージョンを返します。

### The mysqli::init() method has been deprecated.

[mysqli::init](https://www.php.net/manual/ja/mysqli.init.php)が[非推奨になりました](https://qiita.com/rana_kualu/items/c894b2160d1f8799eed2#mysqliinit)。

これは生成メソッドなのに何故かクラスメソッドではなくインスタンスメソッドであり、使い道がわからない代物でした。


## OCI8

### The INI directive oci8.old_oci_close_semantics has been deprecated.

ini設定[oci8.old_oci_close_semantics](https://www.php.net/manual/ja/oci8.configuration.php#ini.oci8.old-oci-close-semantics)が[非推奨になりました](https://qiita.com/rana_kualu/items/c894b2160d1f8799eed2#oci8old_oci_close_semantics-ini-setting)。

この設定はだいぶ昔に後方互換性だけのために導入されたものなので、そろそろ不要です。

## ODBC

### odbc_result_all() has been deprecated.

関数[odbc_result_all()](https://www.php.net/odbc_result_all)が[非推奨になりました](https://qiita.com/rana_kualu/items/c894b2160d1f8799eed2#odbc_result_all)。

取得した結果をいきなりHTMLテーブルに入れて表示する、しかもHTMLエスケープしない、という意味のわからない関数です。

## PDO

### The PDO::FETCH_SERIALIZE mode has been deprecated.

定数[PDO::FETCH_SERIALIZE](https://www.php.net/manual/ja/pdo.constants.php)が[非推奨になりました](https://wiki.php.net/rfc/phase_out_serializable#pdofetch_serialize)。

これは内部的にSerializableインターフェイスを使っていたため、Serializableと共にこちらも非推奨になります。
しかしそれ以前に、実は[そもそも動いていなかった](https://bugs.php.net/bug.php?id=68802)とかなんとかいう話があるっぽいですが。

## PgSQL

### Not passing the connection argument to PgSQL functions and using the default connection is deprecated.

[pg_query()](https://www.php.net/pg_query)など一部のPgSQL関数を、引数`$connection`を渡さずに呼び出すことが[非推奨になりました](https://qiita.com/rana_kualu/items/c894b2160d1f8799eed2#calling-overloaded-pgsql-functions-without-the-connection-argument)。

コネクションを渡しましょう。

## SOAP

### The ssl_method option for the SoapClient constructor has been deprecated

[SoapClient::__construct()](https://www.php.net/manual/ja/soapclient.construct.php)のオプション`ssl_method`が[非推奨になりました](https://qiita.com/rana_kualu/items/c894b2160d1f8799eed2#ssl_method-option-to-soapclient-constructor)。

かわりに`context`オプションを使いましょう。

## Standard

### Calling key(), current(), next(), prev(), reset(), or end() on objects is deprecated.

オブジェクトに対する配列ポインタ操作関数の使用が[非推奨になりました](https://qiita.com/rana_kualu/items/c894b2160d1f8799eed2#key-current-next-prev-and-reset-on-objects)。

詳しくは[配列ポインタ操作関数はIteratorを無視する](https://qiita.com/rana_kualu/items/2a9d18019dd18b5bd2a9)に書きましたが、かなり不安な挙動であるため禁止されます。

### The strptime() function has been deprecated.

関数[strptime()](https://www.php.net/manual/ja/function.strptime.php)が[非推奨になりました](https://qiita.com/rana_kualu/items/c894b2160d1f8799eed2#strptime)。

この関数はプラットフォームやロケールに影響を受けてしまうためです。
影響を受けない[DateTime::createFromFormat()](https://www.php.net/manual/ja/datetime.createfromformat.php)などを使いましょう。

### The auto_detect_line_endings ini setting has been deprecated.

ini設定[oci8.old_oci_close_semantics](https://www.php.net/manual/ja/filesystem.configuration.php#ini.auto-detect-line-endings)が[非推奨になりました](https://qiita.com/rana_kualu/items/c894b2160d1f8799eed2#auto_detect_line_endings-ini-setting)。

古いMacと互換するためだけの機能なので、もはや不要です。

### The FILE_BINARY and FILE_TEXT constants are deprecated.

定数[FILE_BINARYとFILE_TEXT](https://www.php.net/manual/ja/filesystem.constants.php)が[非推奨になりました](https://qiita.com/rana_kualu/items/c894b2160d1f8799eed2#file_binary-and-file_text-constants)。

これらは定義されていただけで、何の効果もありませんでした。


# Changed Functions

動作に変更のあった関数。

## Core

### Properties order used in foreach, var_dump(), serialize(), object comparison etc. was changed.

各関数やループにおいて、オブジェクトのプロパティ出力の順序が規定・文書化されました。
親クラス→子クラスの順番です。

これまでは順序が規定されておらず、実装に依存する状態でした。

## Filter

### The FILTER_FLAG_ALLOW_OCTAL flag of the FILTER_VALIDATE_INT filter now accept octal string with the leading octal prefix ("0o"/"0O")

フィルタフラグ[FILTER_FLAG_ALLOW_OCTAL](https://www.php.net/manual/ja/filter.filters.validate.php)が、"0o123"のような値を受け入れるようになりました。

8進数表記として"0o123"ができるようになったので、そのための変更です。

## GMP

### All GMP function now accept octal string with the leading octal prefix ("0o"/"0O")

全ての[GMP関数](https://www.php.net/manual/ja/ref.gmp.php)が、"0o123"のような値を受け入れるようになりました。

8進数表記として"0o123"ができるようになったので、そのための変更です。

```php
gmp_init('0o123');

// PHP8.1
エラー出ない

// PHP8.0
Fatal error: Uncaught TypeError: gmp_init(): Argument #1 ($num) is not an integer string
```

## PDO ODBC

### PDO::getAttributes() with PDO::ATTR_SERVER_INFO and PDO::ATTR_SERVER_VERSION now return values instead of throwing PDOException.

[PDO::getAttribute()](https://www.php.net/manual/ja/pdo.getattribute.php)へ引数`PDO::ATTR_SERVER_INFO`や`PDO::ATTR_SERVER_VERSION`を渡すと、エラーを出すかわりに値を返すようになりました。

ODBCだけなので、PDO_MySQL等はこれまでも問題なく値を取得できていました。

## Reflection

### ReflectionProperty::setAccessible() and ReflectionMethod::setAccessible() no longer have an effect.

[ReflectionProperty::setAccessible()](https://www.php.net/manual/ja/reflectionproperty.setaccessible.php)と[ReflectionMethod::setAccessible()](https://www.php.net/manual/ja/reflectionmethod.setaccessible.php)が、[何の効果も持たなくなりました](https://qiita.com/rana_kualu/items/a6601b49e0591eb42200#make-reflection-setaccessible-no-op)。

privateなプロパティにも、リフレクション経由であれば即アクセスできるようになります。

```php
class HOGE{
    private static $foo = 'bar';
}

var_dump((new ReflectionProperty(HOGE::class, 'foo'))->getValue());

// PHP8.1
bar

// PHP8.0
Fatal error: Uncaught ReflectionException: Cannot access non-public property
```

どうせ毎回`setAccessible(true)`するんだから最初からデフォルトでいいだろ、という判断です。

## Standard

### syslog() is now binary safe.

関数[syslog()](https://www.php.net/manual/ja/function.syslog)がバイナリセーフになりました。


# New Functions

新しい関数。

## Core

### array_is_list(array $array)

関数[array_is_list()](https://www.php.net/manual/ja/function.array-is-list)が[追加されました](https://qiita.com/rana_kualu/items/a6601b49e0591eb42200#add-array_is_listarray-array-bool)。

0始まりでキーの抜けがない配列である場合のみtrueになります。

```php
array_is_list([0=>1, 1=>2]); // true
array_is_list([0=>1, 2=>2]); // false
```

他言語で言うところの配列であるかを区別できます。



## pcntl

### Added pcntl_rfork for FreeBSD variants

FreeBSD向けに関数[pcntl_rfork()](https://www.php.net/manual/ja/function.pcntl-rfork.php)が追加されました。

[pcntl_fork()](https://www.php.net/manual/ja/function.pcntl-fork.php)と何がちがうのかはよくわかりません。

## Reflection

### Added ReflectionFunctionAbstract::getClosureUsedVariables

メソッド[ReflectionFunctionAbstract::getClosureUsedVariables()](https://www.php.net/manual/ja/function.array-is-list)が追加されました。

無名関数に渡された変数を取り出すことができます。

```php
$foo = 1;
$function = function () use ($foo) { };

$reflector = new ReflectionFunction($function);
var_dump($reflector->getClosureUsedVariables()); // ["foo"=>1]
```

どんなときに使うんだこれ。


## Standard

### Added fsync() and fdatasync()

関数[fsync()](https://www.php.net/manual/ja/function.fsync.php)および[fdatasync](https://www.php.net/manual/ja/function.fdatasync.php)が[追加されました](https://qiita.com/rana_kualu/items/a6601b49e0591eb42200#fsync-function)。

C言語の[fsync・fdatasync](https://linuxjm.osdn.jp/html/LDP_man-pages/man2/fsync.2.html)のラッパーのようです。

## Sodium

### Added the XChaCha20 stream cipher interface functions

関数`sodium_crypto_stream_xchacha20`・`sodium_crypto_stream_xchacha20_keygen`・`sodium_crypto_stream_xchacha20_xor`が追加されました。

[libsodium](https://libsodium.gitbook.io/doc/advanced/stream_ciphers/xchacha20)がXChaCha20に対応したので、[Sodiumライブラリ](https://www.php.net/manual/ja/book.sodium.php)が追随したようです。

### Added the Ristretto255 functions

関数`sodium_crypto_core_ristretto255_add()`・`sodium_crypto_core_ristretto255_from_hash()`・`sodium_crypto_core_ristretto255_is_valid_point()`・`sodium_crypto_core_ristretto255_random()`・`sodium_crypto_core_ristretto255_scalar_add()`・`sodium_crypto_core_ristretto255_scalar_complement()`・`sodium_crypto_core_ristretto255_scalar_invert()`・`sodium_crypto_core_ristretto255_scalar_mul()`・`sodium_crypto_core_ristretto255_scalar_negate()`・`sodium_crypto_core_ristretto255_scalar_random()`・`sodium_crypto_core_ristretto255_scalar_reduce()`・`sodium_crypto_core_ristretto255_scalar_sub()`・`sodium_crypto_core_ristretto255_sub()`・`sodium_crypto_scalarmult_ristretto255()`・`sodium_crypto_scalarmult_ristretto255_base()`が追加されました。

[libsodium](https://libsodium.gitbook.io/doc/advanced/point-arithmetic/ristretto)がRistrettoに対応したので、[Sodiumライブラリ](https://www.php.net/manual/ja/book.sodium.php)が追随したようです。


# New Classes and Interfaces

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

## Intl

### Added IntlDatePatternGenerator

クラス[IntlDatePatternGenerator](https://www.php.net/manual/ja/class.intldatepatterngenerator.php)が[追加されました](https://qiita.com/rana_kualu/items/a6601b49e0591eb42200#add-intldatepatterngenerator)。

[Intlのそれ](https://unicode-org.github.io/icu-docs/apidoc/dev/icu4c/classicu_1_1DateTimePatternGenerator.html)のラッパーです。

```php
$skeleton = 'yyyyMMddHmmss';

(new \IntlDatePatternGenerator('ja_JP'))->getBestPattern($skeleton); // "yyyy/MM/dd H:mm:ss"
(new \IntlDatePatternGenerator('en_US'))->getBestPattern($skeleton); // "MM/dd/yyyy, HH:mm:ss"
(new \IntlDatePatternGenerator('pt_BR'))->getBestPattern($skeleton); // "dd/MM/yyyy HH:mm:ss"
(new \IntlDatePatternGenerator('de_DE'))->getBestPattern($skeleton); // "dd.MM.yyyy, HH:mm:ss"
```

各国の日時形式に合った感じのフォーマットにしてくれるので国際化対応がやりやすくなります。
ただ渡せるフォーマットが[date](https://www.php.net/manual/ja/datetime.format.php)のやつじゃなくて[ICUのフォーマット](https://unicode-org.github.io/icu/userguide/format_parse/datetime/)なのでめんどくさい。


# Removed Extensions and SAPIs

削除されたエクステンション・SAPIは無し。

# Other Changes to Extensions

その他の変更点。

## GD
### imagewebp() can do lossless WebP encoding by passing IMG_WEBP_LOSSLESS as quality.

関数[imagewebp()](https://www.php.net/manual/ja/function.imagewebp.php)は、引数qualityに定数IMG_WEBP_LOSSLESSを渡すとロスレス圧縮できるようになりました。

## Mbstring

### Unicode data tables have been updated to Unicode 14.

Unicodeテーブルが[Unicode 14](http://www.unicode.org/versions/Unicode14.0.0/)に更新されました。

## MySQLi

### The mysqli_stmt::next_result() and mysqli::fetch_all() methods are now available when linking against libmysqlclient.

[libmysqlclient](https://www.php.net/manual/ja/mysqlinfo.library.choosing.php)を使っている場合でも、
[mysqli_stmt::next_result](https://www.php.net/manual/ja/mysqli-stmt.next-result.php)と[mysqli_result::fetch_all
](https://www.php.net/manual/ja/mysqli-result.fetch-all.php)が使えるようになりました。

まあ余程の理由でもないかぎりmysqlndを使いましょう。

## OpenSSL

### The OpenSSL extension now requires at least OpenSSL version 1.0.2.

[OpenSSLエクステンション](https://www.php.net/manual/ja/book.openssl.php)が要求する[OpenSSLライブラリ](https://www.openssl.org/)の最低バージョンが1.0.2になりました。

[これまで](https://www.php.net/manual/ja/openssl.requirements.php)は、PHP7.0以降OpenSSL0.9.8以上、PHP7.1以降OpenSSL1.0.1以上でした。

### OpenSSL 3.0 is now supported.

[OpenSSL3.0](https://www.openssl.org/)がサポートされました。

デフォルトではレガシーな暗号化形式の多くが無効化されているようです。

## Phar

### Use SHA256 by default for signature.

pharアーカイブの[シグネチャ](https://www.php.net/manual/ja/phar.fileformat.signature.php)のデフォルトがSHA256になりました。

これまではSHA1でした。

### Add support for OpenSSL_SHA256 and OpenSSL_SHA512 signature.

pharアーカイブの[シグネチャ](https://www.php.net/manual/ja/phar.fileformat.signature.php)がOpenSSL_SHA256とOpenSSL_SHA512をサポートしました。

[Phar::setSignatureAlgorithm](https://www.php.net/manual/ja/phar.setsignaturealgorithm.php)で設定可能です。

## SNMP

### add SHA256 and SHA512 for security protocol.

[SNMP](https://www.php.net/manual/ja/book.snmp.php)がSHA256とSHA512をサポートしました。

[SNMP::setSecurity](https://www.php.net/manual/ja/snmp.setsecurity.php)で設定可能です。

## Standard

### --with-password-argon2 now uses pkg-config to detect libargon2.

コンパイルオプション`-with-password-argon2`は、`libargon2`の場所を環境変数`PKG_CONFIG_PATH`ではなく`pkg-config`を使って探すようになりました。

Windowsには関係ないのでよくわかりません。

### --with-external-libcrypt now allows to use system libcrypt/libxcrypt instead in PHP own implementation.

コンパイルオプション`--with-external-libcrypt`を指定すると、システムに入っているlibcrypt/libxcryptを使用します。

未指定の場合は、これまでどおりPHPに組み込まれている暗号化処理を使用します。
Windowsには関係ないのでよくわかりません。


# New Global Constants

グローバル定数。

## MySQLi

### MYSQLI_REFRESH_REPLICA has been added as a replacement for MYSQLI_REFRESH_SLAVE

定数[MYSQLI_REFRESH_REPLICA](https://www.php.net/manual/ja/mysqli.constants.php)が追加されました。
値はMYSQLI_REFRESH_SLAVEと同じです。
そしてMYSQLI_REFRESH_SLAVEは将来のバージョンで削除されます。

ポリがコレでなんちゃらのアレです。

## Sockets

### The following socket options are now defined

定数[SO_ACCEPTFILTER / SO_DONTTRUNC / SO_WANTMORE / SO_MARK / TCP_DEFER_ACCEPT](https://www.php.net/manual/ja/sockets.constants.php)が追加されました。

[BSDソケット](https://www.freebsd.org/cgi/man.cgi?query=getsockopt&sektion=2&manpath=FreeBSD+9.0-RELEASE)のラッパーのようです。


# Changes to INI File Handling

iniファイルの変更点。

## The log_errors_max_len ini setting has been removed.

ini設定[log_errors_max_len](https://www.php.net/manual/ja/errorfunc.configuration.php#ini.log-errors-max-len)が削除されました。

実はPHP8.0以降効果がなかったんだよとか言ってるんだけど、これまでそんな話出てきてたっけ？


## A leading dollar in a quoted string can now be escaped.

二重引用符で囲まれた先頭の`$`をエスケープできるようになりました。
すなわち`"\${"`は`"${"`と解釈されます。

とか書いてあるんだけど、これ[ずっと前からそうなってる](https://3v4l.org/gONub)んですよね。
いったい何を言いたいのかよくわからない。


## Backslashes in double quoted strings are now more consistently treated as escape characters.

二重引用符で囲まれた文字列のエスケープの扱い方がより一貫的になりました。
例として、`"foo\\"`の後ろに改行以外の文字があったときの動作が変わります。

とか書いてあるんだけど、これも[前から同じ](https://3v4l.org/OBh7m)なんですよね。
例が悪いのか何なのかわからない。


# Windows Support

Windowsのサポートに変更はありません。

即ち、これまでどおり使い続けることができます。

# Performance Improvements

UPGRADINGには何故か何も書かれていないのですが、[ランディングページ](https://www.php.net/releases/8.1/en.php)にパフォーマンスの改善点が記載されています。

・ARM64([AArch64](https://en.wikipedia.org/wiki/AArch64))へのJITバックエンド対応。
・リクエスト毎にクラスを再リンクせず、キャッシュを継続する。
・クラス名の解決の高速化。
・`timelib`および`ext/date`の高速化。
・SPLイテレータの改良。
・serialize/unserializeの最適化。
・いくつかの内部関数(get_declared_classes()・explode()・strtr()・strnatcmp()・dechex()等)の最適化。
・JITの改善。

![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26088/99e05f9c-aff6-94d6-9e2a-373431be597e.png)

JITの無い状態でもSymfonyが23%高速化、WordPressが3.5%高速化されています。

Symfonyが高速化されたということは、Laravelも高速化されるということです。

……いや23%って何だよ。
いくらなんでもおかしくないか？？？


# 感想

PHP8.1で目立つのは、型に関する機能の追加、そしてレガシーの排除です。

列挙型に交差型にnever型に新潟アクセス修飾子にその他諸々と、型の表現方法が大幅に拡充されました。
なんか書いたらなんとなく動くというインターネット黎明期から引き継がれてきた大らかさはますます狭まり、きっかりかっちり型を縛ったstrictプログラミングがPHPでもほぼ主流となっています。
まあ、当時のように多少ゆるふわでもなあなあでどうにかなる時代はとうに過ぎ去り、ほんの少しでも穴があったら事業存続に繋がる損失になるレベルまでインターネットの領域が広まってきたので、これは仕方のない方向性であると言えるでしょう。

そしてFiberはいまだ未知数ですが、もしかしたら今後のPHPのパラダイムが転換するほどの機能になるかもしれません。
何も起こらないかもしれません。

そしてどんどん新機能が追加され続けているにもかかわらず、何故か高速化も相変わらず進んでいます。
ふしぎですね。

今回はE_DEPRECATEDの追加が目立ちますが、それ以外でいきなり動かなくなるって事態はほぼ無いはずなので、PHP8.0で動いているコードなら概ねそのままいけると思います。
とはいえ初物に飛びつくのは危ないので、PHP8.1.3くらいになったら移行を検討してみてはいかがでしょうか。

これからのPHPは、[Nikitaの離脱](https://qiita.com/rana_kualu/items/eaf97694f25a62f93a7e)という痛手こそあったものの、同時に[PHP財団が設立](https://blog.jetbrains.com/phpstorm/2021/11/the-php-foundation/)され、大きな節目を迎えました。
この試みがうまくいけば、今後もPHPはきっと進化し続けることでしょう。