列挙型(PHP 8.1)
CoddyのPHPジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 59/91。
PHP 8.1 より前は、ステータスや型のような固定された値の集合を表すには、class 定数やマジック文字列を使う必要がありました。どちらもエラーが発生しやすい方法です。列挙型(enumerations)を使うと、あらかじめ定義された特定の値だけを保持できる型を適切に定義できます。
enumキーワードを使用してenumをDefineします。
<?php
enum Status {
case Pending;
case Active;
case Completed;
}
$status = Status::Active;
echo $status->name;
出力:
Active列挙型には backed 値(文字列または整数値が each case に関連付けられたもの)も設定できます。これは、データベースや API に列挙型を保存する場合に便利です:
<?php
enum Status: string {
case Pending = 'pending';
case Active = 'active';
case Completed = 'completed';
}
$status = Status::Active;
echo $status->value;
出力:
activebacked 列挙型には、その値から列挙型を作成する from() メソッドと、invalid な値に対してエラーをスローする代わりに null を返す tryFrom() が用意されています。
<?php
$status = Status::from('active'); // Status::Active を返す
$invalid = Status::tryFrom('unknown'); // null を返す
列挙型にはメソッドも含めることができるため、関連するロジックをカプセル化するうえで強力です。列挙型は型ヒントとシームレスに連携し、関数が有効な値だけを accept するようにできるので、文字列が期待される選択肢と一致するかを毎回確認する必要がなくなります。
チャレンジ
簡単注文ステータスを型安全な方法で表現するために enum を使用する注文管理システムを構築しましょう。誤記や無効な値につながる可能性のある文字列に頼る代わりに、各ステータスをデータベースで扱いやすい値に対応付ける backed enum を作成します。
コードを3つのファイルに分けて整理します。
OrderStatus.php:4つの cases を持つ、文字列 backed enum のOrderStatusを Create します。Pendingは'pending'に backed されますProcessingは'processing'に backed されますShippedは'shipped'に backed されますDeliveredは'delivered'に backed されます
label()method を追加します。- Pending は
"Awaiting confirmation"を返します - Processing は
"Being prepared"を返します - Shipped は
"On the way"を返します - Delivered は
"Order complete"を返します
Order.php:enum を使用するOrderclass を Create します。OrderStatus ファイルを Include します。class は次のようにします。- constructor promotion を使用して、注文 ID(string)と
OrderStatusを constructor で accept する getInfo()method は"Order [id]: [status label]"を返すgetStatusValue()method はステータスの backed value を返す(データベースへの保存に便利です)
- constructor promotion を使用して、注文 ID(string)と
main.php:Order ファイルを Include します。2つの input、つまり注文 ID とステータス文字列("shipped"のような値)を受け取ります。tryFrom()を使用して、文字列 input を安全にOrderStatusenum に convert します。ステータスが有効な場合は、Orderを Create して2行を print します。getInfo()の結果getStatusValue()の結果
"Invalid status"を print します。
この challenge は、enum がどのように型安全性を提供するかを示します。Order class は有効なステータスのみを accept でき、tryFrom() method によって、無効な値のリスクなしに user input を安全に処理できます。
自分で試してみよう
<?php
require_once 'Order.php';
// 入力を読み取る
$orderId = trim(fgets(STDIN));
$statusString = trim(fgets(STDIN));
// TODO: OrderStatus::tryFrom() を使用してステータス文字列を安全に列挙型に変換する
// tryFrom() は値が無効な場合に null を返す
// TODO: ステータスが有効な場合、Order を作成して以下を出力する:
// - getInfo() の結果
// - getStatusValue() の結果
// TODO: If the status is invalid, print "Invalid status"
?>このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: PHPオンラインコンパイラ