はじめに
遅れました。この記事は PHP アドベントカレンダー ギリギリ3日目の記事です。
昨日は fyui001 さんの記事でした。
先日、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にバージョンアップすることをおすすめします。
1日目の rana_kualu さんの記事と結構内容がかぶってしまいました。お許しください。
余談: ドメイン駆動設計について
これらの機能は、ドメイン駆動設計で実装するときもめちゃめちゃ便利です。
「ドメイン駆動設計」については、こちらの本がおススメです。これまで、ドメイン駆動設計の本は難しいものばかりでしたが、この本は具体的な実装から説明が始まるため、エンジニアにとってわかりやすい内容になっています。
無料のWeb 版もあるので、まずはそちらから読んでみてください。
https://nrslib.com/bottomup-ddd/
本はこちら