猫でもわかるWebプログラミングと副業

本業エンジニアリングマネージャー。副業Webエンジニア。Web開発のヒントや、副業、日常生活のことを書きます。

PHP 8.0 / 8.1 で個人的にめっちゃ使いたい機能3選

f:id:yoshiki_utakata:20210510220646p:plain

はじめに

遅れました。この記事は PHP アドベントカレンダー ギリギリ3日目の記事です。

qiita.com

昨日は fyui001 さんの記事でした。

qiita.com

先日、PHP 8.0 の新機能や、8.1で実装予定の機能を「この機能いいなー」とか「PHP 8.1 早く来てほしいなー」と眺めていました。

そしてついに、2021年11月25日、PHP 8.1 がリリースされました。

https://www.php.net/archive/2021.php#2021-11-25-1

そこで、僕が個人的に選ぶ、 PHP 8.0、 PHP 8.1 でめちゃめちゃ使いたい機能3選を紹介します。

PHP 8.0 / 8.1 で個人的にめっちゃ使いたい機能3選

名前付き引数(PHP 8.0)

名前付き引数が PHP 8.0 で追加されました。

https://www.php.net/manual/ja/functions.arguments.php#functions.named-arguments

他の言語には当然のようにある名前付き引数。この変更はPHPerたちも待ち望んでいたでしょう。

<?php

class Hoge
{
    public static function myFunction(string $name = null, int $age = null)
    {
        var_dump($name);
        var_dump($age);
    }
}

Hoge::myFunction(name: 'utakata', age: 17);
// => string(7) "utakata"
// => int(17)

Hoge::myFunction(name: 'utakata');
// => string(7) "utakata"
// => NULL

Hoge::myFunction(age: 17);
// => NULL
// => int(17)

Hoge::myFunction();
// => NULL
// => NULL

これまでは、null なパラメータに対して、いちいち null を指定する必要がありましたが、これで関数呼び出しがかなり書きやすくなります。

コンストラクタのプロモーション(コンストラクタ引数のプロパティ化)

PHP では、エンティティなどを実装するために、以下のようなクラスを実装することが多いです。

<?php

class Student
{
    private $name;
    private $age;

    public function __construct(string $name, int $age)
    {
        $this->name = $name;
        $this->age = $age;
    }

    public function getName(): string
    {
        return $this->name;
    }

    public function getAge(): int
    {
        return $this->age;
    }
}

これを、このようにかけます。

<?php

class Student
{
    public function __construct(
        private string $name,
        private int $age
    ) {
        $this->name = $name;
        $this->age = $age;
    }

    public function getName(): string
    {
        return $this->name;
    }

    public function getAge(): int
    {
        return $this->age;
    }
}

$s = new Student('utakata', 17);

var_dump($s->getName());
// => string(7) "utakata"

var_dump($s->getAge());
// => int(17)

記述が少なくなり、完結になります。

この機能を、PHPでは「コンストラクタのプロモーション」と呼びます。

Readonly Property

Readony property は、読めるけど書き込めないプロパティです。

これも、エンティティのボイラープレートをへらすのに役立ちます。

<?php

class Hoge
{
    public readonly string $status;

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

    public function setStatus(string $status)
    {
        $this->status = $status;
    }
}

$h = new Hoge('success');

var_dump($h->status);
// => string(7) "success"

$h->status = 'failed';
// => Fatal error: Uncaught Error: Cannot modify readonly property Hoge::$status in /code/named_arguments.php:21

$h->setStatus('failed');
// => Fatal error: Uncaught Error: Cannot modify readonly property Hoge::$status in /code/named_arguments.php:14

readonly は、一度セットされると、セッターでアクセスしたとしても更新できません。

クラスの内部で値が初期化されれば、コンストラクタでなくても大丈夫です。

<?php

class Hoge
{
    public readonly ?string $status;

    public function __construct()
    {
    }

    public function setStatus($status)
    {
        $this->status = $status;
    }
}

$h = new Hoge();

// セッターで初期化することもできる
$h->setStatus('success');

var_dump($h->status);
// => string(7) "success"

初期化せずに値にアクセスするとエラーになります。

<?php

class Hoge
{
    public readonly ?string $status;

    public function setStatus($status)
    {
        $this->status = $status;
    }
}

$h = new Hoge('success');

var_dump($h->status);
// => Fatal error: Uncaught Error: Typed property Hoge::$status must not be accessed before initialization in /code/named_arguments.php:19

また、クラスの外から値を初期化することができません。

<?php

class Hoge
{
    public readonly ?string $status;
}

$h = new Hoge();

$h->status = 'success';
// => Fatal error: Uncaught Error: Cannot initialize readonly property Hoge::$status from global scope in /code/named_arguments.php:20

また、値を2回セットすることもできません。

<?php

class Hoge
{
    public readonly ?string $status;

    public function __construct(string $status)
    {
        $this->status = $status;
        $this->status = $status;
        // => Fatal error: Uncaught Error: Typed property Hoge::$status must not be accessed before initialization in /code/named_arguments.php:19
    }
}

ちなみに、 readonly property には型が必須なようです。

<?php

class Hoge
{
    public readonly $status;
}

// => Fatal error: Readonly property Hoge::$status must have type in /code/named_arguments.php on line 5

コンストラクタのプロモーションと組み合わせることもできます。

<?php

class Student
{
    public function __construct(
        public readonly string $name,
        public readonly int $age
    ) {
    }
}

$s = new Student('utakata', 17);

var_dump($s->name);
// => string(7) "utakata"

var_dump($s->age);
// => int(17)

おわりに

今回は気になる機能として、

  • 名前付き引数
  • コンストラクタのプロモーション
  • Readonly Property

を紹介しました、どれも、DDDにおけるエンティティなどを実装する際に非常に便利で。重宝しそうです。

他にも PHP 8.1 で気になる機能として

  • Enumの追加
  • First-class Callable Syntax
  • New in initializers
  • Pure Intersection Types

などなど、実用的な機能追加が盛りだくさんなので、ぜひチェックして、PHP8.1にバージョンアップすることをおすすめします。

www.php.net

1日目の rana_kualu さんの記事と結構内容がかぶってしまいました。お許しください。

余談: ドメイン駆動設計について

これらの機能は、ドメイン駆動設計で実装するときもめちゃめちゃ便利です。

「ドメイン駆動設計」については、こちらの本がおススメです。これまで、ドメイン駆動設計の本は難しいものばかりでしたが、この本は具体的な実装から説明が始まるため、エンジニアにとってわかりやすい内容になっています。

無料のWeb 版もあるので、まずはそちらから読んでみてください。

https://nrslib.com/bottomup-ddd/

本はこちら