Code Fix

上級

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;
Fatal error: Uncaught ValueError: "pending" is not a valid backing value for enum Status in main.php:6

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;
Fatal error: Uncaught ValueError: 3 is not a valid backing value for enum Level in main.php:6

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;
Fatal error: Uncaught ValueError: "EUR" is not a valid backing value for enum Currency in main.php:6

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;
Fatal error: Uncaught ValueError: "green" is not a valid backing value for enum Color in main.php:6

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;
Fatal error: Uncaught ValueError: 9 is not a valid backing value for enum Priority in main.php:6

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には、そもそも対応する値からの逆引きという概念自体がありません。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)