PHP 8.1 から使えるようになりました。Enum 自体は、ユーザランド実装の亜種を使うことが多くて、PHP 組み込みの Enum の経験が足りてなかったので、今回学びなおしてみることにした。
復習
例として適当かどうかは別として、Animal
を考えてみよう。
1 | <?php |
これで、 Animal
は型として使えるようになったので、こんな引数定義が可能になる。
1 | <?php |
この結果は、こうなります。
1 | enum Animal::Cat; |
ここまでは、列挙型の基本。上の cry
メソッドは、Animal
型のみが入ります。他の型を入れると、実行時にエラーになりますし、PHPStan などでエラーを検出することがかのうです。
例えば、文字列を入れると…
1 | PHP Fatal error: Uncaught TypeError: cry(): Argument #1 ($animal) must be of type Animal, string given, called in /tmp/hoge.php on line 15 and defined in /tmp/hoge.php:9 |
cry
メソッドは意図した値のみが渡ってくるので、堅牢なプログラムになりました。
Backed Enum
PHP マニュアルにも、まさにそのままの説明が載っています。
列挙型の case をデータベースや、 類似のデータストアで読み書きする必要があるケースが多くあります。 よって、ビルトインの (シリアライズ可能であることが自明な) スカラー値を持つ case があると、本質的に役に立ちます。
さきほどの例を使って続けると、例えばデータベースのカラムに animal_type
というものがあったとして、1 が Cat、 2 が Dog を表すとします。(ここでは、データベースアンチパターンについては無視します)
この時に、 Animal::Cat
が データベースの値である 1
を表してくれると便利ですし、1, 2 以外の値がカラムに登録される心配が少なくなります。Backed Enum の値に設定できるのは、スカラー型(int, string) のみです。
1 | <?php |
結果は、こうなります。
1 | int(1) |
from, tryFrom
Backed Enum については、from
tryFrom
でスカラー型から Enum の Case を返すことができます。
1 | <?php |
from
と tryFrom
の違いは、異常値にたいして エラーにするか、NULLを返すかです。
その他
定数式での列挙型
列挙型のCaseはconstでも使えるけど、Backed Enum の値は使えない。
1 | <?php |
Case に合わせた柔軟な値の取り扱いをする場合は、 Enum 型の方にメソッドを定義したほうが良さそう。
値のリスト
cases メソッドが定義されているので、Loop で回すときは、こっちを使うと便利
1 | <?php |
配列が出力されます。
1 | array(2) { |
個人的な感想
Backed Enum の値の参照は、変数定義、コンスト定義時には使えないので、この辺りを柔軟に使いたい場合は、Enum側を拡張してあげる方向で考えたほうがスッキリしそう。
try
, tryFrom
, cases
は単純に知らなかったので、今回ちゃんとマニュアルを読み直してよかった。