enumのfrom()に存在しない値を渡すと ValueError になる
バックドenum(値を持つenum)のfrom()メソッドは、対応するcaseが存在しない値を渡すとValueErrorを投げます。外部からの入力値をそのままfrom()に渡す場合は、事前の検証やtryFrom()の利用が必要です。
エラーメッセージの読み方
Fatal error: Uncaught ValueError: "pending" is not a valid backing value for enum Status in main.php:6
main.php- ファイル名
6- 行番号 — 実際にクラッシュした行
ValueError- 例外クラス — 何が起きたか。ここを検索するのが最短です
"pending" is not a valid backing value for enum Status- 内容 — どの値が問題だったか
このエラーが出る典型パターン
パターン1
1 <?php 2 enum Status: string { 3 case Active = 'active'; 4 case Inactive = 'inactive'; 5 } 6 $s = Status::from('pending'); ^ 7 echo $s->value;
Statusにはpendingというcaseがありません。from()は該当するcaseが無い値を渡すとValueErrorを投げます。定義済みの値を渡す必要があります。
直し方: 'pending' を 'active' にします。
パターン2
1 <?php 2 enum Level: int { 3 case Low = 1; 4 case High = 2; 5 } 6 $l = Level::from(3 ); ^ 7 echo $l->name;
Levelには3というcaseがありません。from()は該当するcaseが無い値でValueErrorになります。定義済みの1か2を渡す必要があります。
直し方: 3 を 1 にします。
パターン3
1 <?php 2 enum Currency: string { 3 case Yen = 'JPY'; 4 case Dollar = 'USD'; 5 } 6 $c = Currency::from('EUR'); ^ 7 echo $c->name;
CurrencyにEURというcaseは定義されていません。定義済みの値(JPYやUSD)を渡す必要があります。
直し方: 'EUR' を 'JPY' にします。
パターン4
1 <?php 2 enum Color: string { 3 case Red = 'red'; 4 case Blue = 'blue'; 5 } 6 $c = Color::from('green'); ^ 7 echo $c->value;
Colorにはgreenというcaseがありません。from()は該当するcaseが無い値を渡すとValueErrorを投げます。
直し方: 'green' を 'red' にします。
パターン5
1 <?php 2 enum Priority: int { 3 case Low = 1; 4 case High = 2; 5 } 6 $p = Priority::from(9 ); ^ 7 echo $p->name;
Priorityには9というcaseがありません。定義済みの1か2を渡す必要があります。
直し方: 9 を 1 にします。
よくある誤解
「from()は該当が無ければnullを返すだけのはず」という思い込みは誤りです。nullを返すのはtryFrom()の役割で、from()は該当が無ければ必ず例外を投げます。
実務での勘所
from()とtryFrom()という失敗時の挙動が違う2つのメソッドを両方用意するのは、他の言語でも見られる一般的な設計パターンです(C#のParseとTryParseと同じ考え方です)。値が必ず正しいはずだと確信できる場面ではfrom()、外部からの入力のように失敗もありうる場面ではtryFrom()を使い分けます。なお、この2つのメソッドはPHP 8.1で追加されたバックドenum(intやstringの値を持つenum)だけが持つ機能で、値を持たない通常のenumのcaseには、そもそも対応する値からの逆引きという概念自体がありません。