PHPバージョン変更点をピックアップ(8.x ～ 8.2)


7.4以前のまとめは[こちらです](https://qiita.com/RyutaKojima/items/d9a968ab6a1721736938)

# [PHP 7.4.x から PHP 8.0.x への移行](https://www.php.net/manual/ja/migration80.php)

[新機能](https://www.php.net/manual/ja/migration80.new-features.php)

- [名前付き引数](https://www.php.net/manual/ja/functions.arguments.php#functions.named-arguments) のサポートが追加されました。
    ```
    myFunction(paramName: $value);
    array_foobar(array: $value);
    
    // 以下の書き方はサポートされていません
    function_name($variableStoringParamName: $value);
    ```

- [アトリビュート](https://www.php.net/manual/ja/language.attributes.php) のサポートが追加されました。
    - `#[Attribute]`
- [コンストラクタのプロパティ昇格機能](https://www.php.net/manual/ja/language.oop5.decon.php#language.oop5.decon.constructor.promotion)
    - > コンストラクタの引数に、アクセス権の修飾子が含まれている場合、 PHP はそれをオブジェクトのプロパティ、かつコンストラクタの引数であると解釈します。 そして、その引数の値をプロパティに代入します。
        ```
        class Point {
            public function __construct(protected int $x, protected int $y = 0) {
            }
        }
        ```

- [union 型](https://www.php.net/manual/ja/language.types.declarations.php#language.types.declarations.composite.union) のサポートが追加されました。
    - `T1|T2|null`
    - `?T1` と `T1|null` は同じです
- [match 式](https://www.php.net/manual/ja/control-structures.match.php) のサポートが追加されました。
    ```
    $food = 'cake';
    
    $return_value = match ($food) {
        'apple' => 'This food is an apple',
        'bar' => 'This food is a bar',
        'cake' => 'This food is a cake',
    };
    
    var_dump($return_value);
    ```
    - 上の例の出力 `string(19) "This food is a cake"`
- [nullsafe 演算子](https://www.php.net/manual/ja/language.oop5.basic.php#language.oop5.basic.nullsafe) (?->) のサポートが追加されました。
    - `$repository?->getUser(5)?->name;`
- その他の新機能
    - [WeakMap](https://www.php.net/manual/ja/class.weakmap.php) クラスが追加されました。
    - [ValueError](https://www.php.net/manual/ja/class.valueerror.php) クラスが追加されました。
    - 任意の数の関数の引数が、可変長引数に置き換えられるようになりました。 但し、型に互換性がある場合に限ります。
        ```
        class A {
             public function method(int $many, string $parameters, $here) {}
        }
        class B extends A {
             public function method(...$everything) {}
        }
        ```
    - static ("遅延静的束縛"における) 型が、 戻り値の型として使えるようになりました
        ```
        class Test {
             public function create(): static {
                  return new static();
             }
        }
        ```
    - オブジェクトのクラス名を `$object::class` と書くことで取得できるようになりました。 この結果は、`get_class($object)` と同じです。
    - new と instanceof が、 `new (expression)(...$args)` や `$obj instanceof (expression)` という形で、任意の式と一緒に使えるようになりました。
    - 変数の文法に一貫性を持たせるため、いくつかの修正が適用されます。 たとえば、Foo::BAR::$baz のような書き方が許可されるようになりました。
    - インターフェイス [`Stringable`](https://www.php.net/manual/ja/class.stringable.php) が追加されました。 クラスが `__toString()` メソッドを定義していた場合、 このインターフェイスが自動的に実装されます。
    - トレイトで、 **private な抽象メソッドを定義** できるようになりました。 このメソッドは、**トレイトを使うクラスで実装されなければなりません**。
    - throw が式として使えるようになりました。
        ```
        $fn = fn() => throw new Exception('Exception in arrow function');
        $user = $session->user ?? throw new Exception('Must have user');
        ```
    - 引数のリストに付ける最後のカンマも、許可されるようになりました。
        ```
        function functionWithLongSignature(
            Type1 $parameter1,
            Type2 $parameter2, // <-- このカンマが許可されるようになりました
        ) {
        }
        ```
    - 変数に保存せずに、 例外をキャッチするために、`catch (Exception)` というコードが書けるようになりました。
    - [mixed 型](https://www.php.net/manual/ja/language.types.declarations.php#language.types.declarations.mixed)のサポートが追加されました。
    - 親クラスで宣言された private メソッドは、 子クラスのメソッドに対して継承ルールを強制しなくなりました
        ```
        class ParentClass {
            private function method1() {}
            private function method2() {}
            private static function method3() {}
            // "final" が意味をなさなくなったので、警告が発生します:
            private final function method4() {}
        }
        class ChildClass extends ParentClass {
            // 親クラスの private メソッドとアクセス権の修飾子が異なっている
            // 以下の全ての宣言が許されるようになりました。
            public abstract function method1() {}
            public static function method2() {}
            public function method3() {}
            public function method4() {}
        }
        ```
    - `(int) $resource` と同じ値を返す [`get_resource_id()` 関数](https://www.php.net/manual/ja/function.get-resource-id.php)が追加されました。 よりわかりやすいAPIで、同じ機能を提供するものです。
    - [InternalIterator](https://www.php.net/manual/ja/class.internaliterator.php) が追加されました。


[下位互換性のない変更点](https://www.php.net/manual/ja/migration80.incompatible.php)

# [PHP 8.0.x から PHP 8.1.x への移行](https://www.php.net/manual/ja/migration81.php)

[新機能](https://www.php.net/manual/ja/migration81.new-features.php)

- 8進数の整数リテラルのプレフィックス指定
    - 8進数の整数値の場合に、 数値リテラルのプレフィックスとして明示的に 0o や 0O を指定できるようになりました。
        ```
        014;  // プレフィックス指定がない 8進数のリテラル
        0o14; // プレフィックスを指定した 8進数のリテラル
        ```
- 文字列をキーとして持つ [配列をアンパック](https://www.php.net/manual/ja/language.types.array.php#language.types.array.unpacking) できるようになりました。
    ```
    $arr1 = [1, 'a' => 'b'];
    $arr2 = [...$arr1, 'c' => 'd']; //[1, 'a' => 'b', 'c' => 'd']
    ```
- 引数を展開した後の名前付き引数
    - 引数を ... で展開した後に、名前付き引数を指定できるようになりました。 e.g. `foo(...$args, named: $arg)`
- ファイルアップロード時の full-path キーのサポート
- [列挙型(Enum)](https://www.php.net/manual/ja/language.enumerations.php) のサポートが追加されました。
    ```
    enum Suit
    {
        case Hearts;
        case Diamonds;
        case Clubs;
        case Spades;
    }
    ```
- [ファイバー(Fibers)](https://www.php.net/manual/ja/language.fibers.php) のサポートが追加されました。
- 第一級callableを生成する記法
    - [`myFunc(...)` という記法](https://www.php.net/manual/ja/functions.first_class_callable_syntax.php) で、 callable から無名関数を生成できるようになりました。 これは、 `Closure::fromCallable('myFunc')` と同等です。
    - 注意: **`...` は文法の一部**であり、**省略形ではありません**。
- [交差型](https://www.php.net/manual/ja/language.types.declarations.php#language.types.declarations.composite.intersection) のサポートが追加されました。
    - `T1&T2`
    - **交差型 は、 union 型 と一緒に使うことはできません。**
- Never 型
    - 戻り値にのみ指定できる型として、 新しく never 型が追加されました。 これは、関数が `exit()` するか、 例外を投げるか、終了しないことを示します。
- 初期化時の new 式の許可
    - `new ClassName()` 式が、引数のデフォルト値の初期化時、 static 変数の初期化時、グローバルな定数の初期化時、 およびアトリビュートの引数として許可されるようになりました。 
    - オブジェクトが define() に渡せるようにもなっています。
- 読み取り専用プロパティ
    - プロパティに対して、[readonly](https://www.php.net/manual/ja/language.oop5.properties.php#language.oop5.properties.readonly-properties) が指定できるようになりました。
        - readonly は、 型付きプロパティ に対してのみ指定できます。 型の制約がないプロパティを読み取り専用にしたい場合、 mixed 型 が使えます。
- クラス定数の final 指定
    - [クラスの定数に対して、 final が指定できる](https://www.php.net/manual/ja/language.oop5.final.php#language.oop5.final.example.php81) ようになりました。 また、インターフェイスの定数も、デフォルトでオーバーライド(上書き)できるようになりました。

[下位互換性のない変更点](https://www.php.net/manual/ja/migration81.incompatible.php)

# [PHP 8.1.x から PHP 8.2.x への移行](https://www.php.net/manual/ja/migration82.php)

[新機能](https://www.php.net/manual/ja/migration82.new-features.php)

- SensitiveParameter アトリビュート
    バックトレースから機密情報を削除するためのアトリビュートとして、
    `#[\SensitiveParameter]` が追加されました。

- error_log_mode INI ディレクティブ
    エラーログファイルに対してパーミッションを設定できる INI ディレクティブとして、
    `error_log_mode` が追加されました。

- 定数式の中で、列挙型のプロパティを取得
    定数式の中で、列挙型 のプロパティを取得できるようになりました。

- 型システムの改善
    `null` と `false` が独立した型として使えるようになりました。
    `true` 型が追加されました。
    交差型 と union型 が組み合わせて使えるようになりました。
    その場合、型は DNF として記す必要があります。

- トレイトで定数
    トレイトの中で、定数を定義できるようになりました。

- 読み取り専用クラス
    クラスに対して `readonly`
    を指定する機能 がサポートされました。

[下位互換性のない変更点](https://www.php.net/manual/ja/migration82.incompatible.php)

[PHP 8.2.x で推奨されなくなる機能](https://www.php.net/manual/ja/migration82.deprecated.php)

- 動的なプロパティの利用
クラスにアトリビュート `#[\AllowDynamicProperties]` を付加していない場合、 動的にプロパティを生成することは推奨されなくなりました。 `stdClass` で動的なプロパティを使うことはまだ許可されています。 マジックメソッド `__get()` / `__set()` を使う場合は、この変更の影響は受けません。 動的なプロパティによる非推奨の警告については、以下によって対応できます:
    - プロパティを宣言する (好ましい対応方法です)
    - クラスにアトリビュート `#[\AllowDynamicProperties]` を付加する (すべての子クラスにも適用されます)
    - 追加のデータをオブジェクトと関連付ける必要があるが、 そのオブジェクトがデータを所有していない場合、 `WeakMap` を使う

- 部分的にしかサポートされていない callable
- `"${var}"` / `"${expr}"` 形式の、文字列への値の埋め込み
    - `"${var}"` と `"${expr}"` 形式の文字列への値の埋め込みは、推奨されなくなりました。 `"$var"`/`"{$var}"` や `"{${expr}}"` 形式をそれぞれ使ってください。