PHP8.0触ってみた 

## 概要
先日PHP8.0がリリースされましたね。
PHPは今年で２５歳だそうで自分の１歳下だと考えると愛着が湧くなあと思ってる今日この頃です。

というわけで気になる機能を試してみようのコーナーです。(n番煎じ)

## 実行環境
一応実行環境を書いておきますと以下のファイルからdocker-composeでコンテナを立ち上げて実行しました。

```yaml

version: '3'

services:
  php:
    image: php:8.0.0-fpm-buster
    volumes:
      - ./src:/src:cached

```


## Named arguments

従来は関数などに引数を渡す時は決められた順序で渡す必要がありましたが、
php８からは引数を渡す時に順番に関係なく変数名に対して渡すことが出来ます。

```php

<?php

$var = in_array(
    needle: 'php8',
    haystack: ['php5', 'php7', 'php8'],
    strict: true
);

var_dump($var);

```

実行結果

```
bool(true)
```

他の言語からの輸入ですね。
渡す引数の順序を気にしなくてよくなるので、呼び出し側のことを考えず修正が出来ますし、可読性が上がったりいいことづくめだと思います。

## Match expression

New条件分岐です。
説明が難しいのすがコードを見てもらえればわかるかなと...（説明放棄）

```php
<?php

function stock($count) {
    return match($count) {
        0 => "在庫なし。",
        1, 2, 3, 4, 5 => "残り{$count}点です。",
        default => "在庫あり。"
    };
}

var_dump(stock(1), stock(0), stock('0'), stock(6));
```

実行結果

```
string(19) "残り1点です。"
string(15) "在庫なし。"
string(15) "在庫あり。"
string(15) "在庫あり。"
```

こんな感じで引数で渡された値に対して、宣言した条件式と比較を行い等しければ、対応した値を返却するというものです。

switch式ととても似てますが、違う点としては

- 厳密比較である(===)
- 分岐を抜ける時breakの記述がいらない(後の分岐には抜けない)
- 全パターン網羅していないと UnhandledMatchErrorがスローされる

といった感じです。

完全上位互換というわけではないので使い分けするのがよさそうですね。
自分的には厳密比較なのがとてもGoodです！

## Union Types

型宣言を複数の型で行うことが出来るようになりました。

```php
<?php

declare(strict_types=1);

class Entity
{
    private int|string|null $id;
    
    public function __construct(int|string|null $id)
    {
        $this->id = $id;
    }

    public function getId(): int|string|null
    {
        return $this->id;
    }
}

function find(int|string|Entity|null $identifier) : int|string|null
{
    if ($identifier instanceof Entity) {
        return $identifier->getId() ?? null;
    }
    return $identifier;
}

var_dump(find(2), find(new Entity(3)));
```
実行結果

```
int(2)
string(1) "3"
```

他言語からの輸入ですね。
より型を意識したコードが書きやすくなりました。

## Constructor Property Promotion

コンストラクタでメンバ変数の定義を書くことが出来るようになりました。
以前はクラス内でメンバ変数の定義、メンバ変数に格納する引数の定義、メンバ変数に引数から得た値をセットする記述が必要でしたが、
PHP８からは引数にメンバ変数の定義を書くだけでオッケーです！

```php

<?php

declare(strict_types=1);

class Entity
{    
    public function __construct(private int|string|null $id)
    {}

    public function getId(): int|string|null
    {
        return $this->id;
    }
}

var_dump((new Entity('3'))->getId());

```
実行結果

```
string(1) "3"
```

## Nullsafe operator


メソッドチェインの途中でnullが入るとそこで処理を止めてくれる記述です。

今までであれば下記のように

```php
<?php

class Chain
{
    public function chain()
    {
        return $this;
    }

    public function null()
    {
        return null;
    }
}

var_dump((new Chain)->chain()->null()->chain());
```
実行結果

```
Fatal error: Uncaught Error: Call to a member function chain() on null in /src/chain.php:16
```

とメソッドチェインの途中でnullが入ってしまうとエラーになってしまっていましたが、
PHP８からは下記のように

```php
<?php

class Chain
{
    public function chain()
    {
        return $this;
    }

    public function null()
    {
        return null;
    }
}

var_dump((new Chain)->chain()->null()?->chain());
```
実行結果

```
NULL
```

と？の記述でnullとなった場合、そこで処理を止めてくれます。

Laravelなどチェインメソッドが多くなりがちなので、便利そうですね。

## まとめ

まだまだ新機能はたくさんありますが、自分が今すぐにでも実務で使いたい！と感じたものをピックアップしてお試ししてみました。

ネイティブコードにコンパイルするJIT対応などは数倍の処理の高速化が出来るようで、近いうちに試してみたいです。

PHPはコードが年々書きやすく読みやすく進化しているし、それに加えてパフォーマンスも上がっていっているのですごいと思いました。(こなみかん)

PHPに置いてかれないように、言語の機能を使いこなして所謂モダンなコードが書けるよう精進します。

---
[:christmas_tree: FORK Advent Calendar 2020](/advent-calendar/2020/fork)
:arrow_left: 4日目 [マテリアルデザインのCSSフレームワーク「Materialize」を触ってみた](https://qiita.com/sk2usa/items/78cc001d14418a098ed0) @sk2usa
:arrow_right: 6日目 [面倒なカレンダー登録はGASにやらせる](https://qiita.com/agoKnife/items/338de5127e5b2b73bd53) @agoKnife