業務に使いそうなPHP8

豚野郎です。(ヌルッ！)

PHP8の変更点について書いていきます。
この記事は個人的にLaravelで、
小〜中規模開発で使う前提で何となく必要そうな変更点を書いていきます。

また、自分が理解できるまでの範囲のものを記載しました。

**ここでは以下2点に関しては記載しません。**
・JITコンパイラー
・新しい定義済みの関数

あくまで、**個人的に業務、且つLaravelで使いそうだと思う構文の変更点**について書いていきます。

**PHP 8.1.14**

# 1. コンストラクタのプロパティ昇格機能
まずPHPの公式にもタイトルと同じことが書かれていませんでしたが、
**私はタイトルの意味がよくわかっていませんでした。**
そこで、PHPのプロパティについて調べました。

https://wepicks.net/phpref-oop-property/#:~:text=%E3%83%97%E3%83%AD%E3%83%91%E3%83%86%E3%82%A3%20%E3%81%AF%20%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AB%E9%96%A2%E9%80%A3%E4%BB%98%E3%81%84%E3%81%9F%E3%83%87%E3%83%BC%E3%82%BF%EF%BC%88%E3%82%AF%E3%83%A9%E3%82%B9%E5%86%85%E5%A4%89%E6%95%B0%EF%BC%89&text=%E3%82%AF%E3%83%A9%E3%82%B9%E5%86%85%E5%A4%89%E6%95%B0%E3%81%AE%E3%82%88%E3%81%86,%E3%81%99%E3%82%8B%E3%81%93%E3%81%A8%E3%82%82%E5%8F%AF%E8%83%BD%E3%81%A7%E3%81%99%E3%80%82

>プロパティ は「オブジェクトに関連付いたデータ」です。クラス内変数のようなものです。変数なので、名前と値があります。プロパティ の宣言で、変数名と初期値を決めることができ、変数名だけ決めておいて値を後から代入することもできます。また、変数名も値も決めずに プロパティ を宣言することも可能です。
プロパティ には アクセス権（可視化）の設定が3種類（public／private／protected）あります。

プロパティに関しては理解できました。

次に、「コンストラクタのプロパティ昇格機能」がどういうことかPHPの公式から調べました。
>PHP 8.0.0 以降では、コンストラクタの引数を 対応するオブジェクトのプロパティに昇格させることができます。

以下のページにあるように、細かく書くと
「コンストラクタの引数をプロパティへ昇格させる機能」
という意味でした。
https://www.php.net/manual/ja/migration80.new-features.php
>コンストラクタの引数をプロパティへ昇格させる機能

PHP7.4とPHP8で書き方を比べます。

- PHP7.4(PHP8でこの書き方でもエラーは出ません)
```sample.php
<?php
    class Test {
        public string $test;

        public function __construct(string $test = 'test') {
            $this->test = $test;
        }

        public function getTest() {
            return $this->test;
        }
    }

    $test = new Test();
    print($test->getTest());
```
```
$ php sample.php
test
```

- PHP8
```sample.php
<?php
    class Test {
        public function __construct(public string $test = 'test') {

        }

        public function getTest() {
            return $this->test;
        }
    }

    $test = new Test();
    print($test->getTest());
```
```
$ php sample.php
test
```

確かに「コンストラクタの引数をプロパティへ昇格させる機能」でした。

# 2. union型
PHP8では「|」を使って、複数型を指定できます。
```sample.php
<?php
    class Test {
        public function getTest(int|string $test) {
            echo $test;
        }
    }

    $test = new Test();
    print($test->getTest('1'));
```
```
$ php sample.php
1
```


# 3. throwが文から式へ
プログラムは以下のサイトから引用
https://tadtadya.com/php8-throw-expression/#index-list-1

```sample.php
<?php
    $callable = fn() => throw new Exception();
    $callable();
```
```
php sample.php
PHP Fatal error:  Uncaught Exception in パス/sample.php:2
Stack trace:
#0 パス/sample.php(3): {closure}()
#1 {main}
  thrown in パス/sample.php on line 2

Fatal error: Uncaught Exception in パス/sample.php:2
Stack trace:
#0 パス/sample.php(3): {closure}()
#1 {main}
  thrown in パス/sample.php on line 2
```

アロー演算子等でも使えるようになったみたいです。
(この辺りは理解が浅いので、今後深めていきます。)

# 4. 弱いマッピング
ソース、説明は以下から引用。
https://kinsta.com/jp/blog/php-8/

>したがって、このRFCではWeakMapクラスが導入され、キーオブジェクトへのリファレンスがそれ以上ない場合、破棄してウィークマッピングから削除できるウィークマップキーとして使用されるオブジェクトが作成されます。

```sample.php
<?php
    $map = new WeakMap;
    $obj = new stdClass;
    $map[$obj] = 42;
    var_dump($map);

    unset($obj);
    var_dump($map);
```
```
php sample.php
object(WeakMap)#1 (1) {
  [0]=>
  array(2) {
    ["key"]=>
    object(stdClass)#2 (0) {
    }
    ["value"]=>
    int(42)
  }
}
object(WeakMap)#1 (0) {
}
```

理解が浅いですが、上記のソースの場合は
$objをunsetすると、$mapの中も一緒に削除されるということですね。
(Laravelを使う上であまり使うかはわかりません。)


# 5. パラメータリストの末尾のカンマ
またですが、以下から引用させてもらいコメントも追記しました。
https://kinsta.com/jp/blog/php-8/

```sample.php
<?php
    class Foo {
        public function __construct(
            string $x,
            int $y,
            # 以下のカンマのこと
            float $z,
        ) {
            // do something
        }
    }
```
今は、引数の最後にもカンマがつけられるようになったと理解しておきます。

# 6. :class構文がオブジェクトで使用できる
```sample.php
<?php
    $std_class = new stdClass;
    var_dump($std_class::class);
```
```
$ php sample.php
string(8) "stdClass"
```

# 7. 名前付き引数
```sample.php
<?php
    function test($one = null, $two= null, $three = null){
        print($three);
    }

    // 以下だと、$threeだけ変更したいのに引数が多くなる
    // test(null, null, '変更');

    // 以下の方法だと、$threeのみの引数で済む
    test(three: '変更');
```
```
$ php sample.php
変更
```

# 8. null安全オペレータ
```sample.php
<?php
    class Test {
        public function getTest($test = null) {

        }
    }

    $test = new Test();

    // getTestメソッドがnullの段階で、$resultはnull
    $result = $test?->getTest('テスト');
    
    print(is_null($result));
```
```
$ php sample.php
1
```

# 9. match式
```sample.php
<?php
    $num = 1;

    // この例だとmatchの引数に、0〜2にマッチしている文字列が入る
    $match = match ($num) {
                0 => 'one',
                1 => 'two',
                2 => 'three',
            };
    
    print($match);
```
```
$ php sample.php
two
```
上記の例で3から上を入れたらエラーが出ました。
```
$ php sample.php
PHP Fatal error:  Uncaught UnhandledMatchError: Unhandled match case 3 in パス/PHP8/sample.php:5
Stack trace:
#0 {main}
  thrown in パス/sample.php on line 5

Fatal error: Uncaught UnhandledMatchError: Unhandled match case 3 in パス/sample.php:5
Stack trace:
#0 {main}
  thrown in パス/sample.php on line 5
```

# 主な参考
ありがとうございました
https://kinsta.com/jp/blog/php-8/