PHPのEnumとは
PHP 8.1から正式に導入された Enum(列挙型) は、決まった値の集合を型安全に表現するための仕組みです。
以前は定数(const)や文字列で代替していた「ステータス」や「カテゴリ」などの概念を、より安全かつ表現力豊かに扱えるようになりました。
<?php
// 以前のやり方(定数で代替)
class OrderStatus
{
const PENDING = 'pending';
const SHIPPED = 'shipped';
const DELIVERED = 'delivered';
}
// PHP 8.1 以降:Enumを使う
enum OrderStatus
{
case Pending;
case Shipped;
case Delivered;
}
定数と違い、Enumは型として扱えるため、関数の引数や戻り値に使うと不正な値の混入を防げます。
Pure EnumとBacked Enum
PHPのEnumには2種類あります。
Pure Enum(純粋な列挙)
値を持たない最もシンプルな形です。
<?php
enum Direction
{
case North;
case South;
case East;
case West;
}
function move(Direction $dir): string
{
return match ($dir) {
Direction::North => '北へ移動',
Direction::South => '南へ移動',
Direction::East => '東へ移動',
Direction::West => '西へ移動',
};
}
echo move(Direction::North); // 北へ移動
型ヒントに Direction を指定することで、Direction::North 以外の値は渡せなくなります。
Backed Enum(値付き列挙)
文字列(string)または整数(int)を紐付けることができます。
<?php
enum Color: string
{
case Red = 'red';
case Green = 'green';
case Blue = 'blue';
}
// 値からEnumを取得する
$color = Color::from('red');
echo $color->name; // Red
echo $color->value; // red
// 存在しない値はfromだと例外、tryFromだとnullを返す
$unknown = Color::tryFrom('yellow'); // null
データベースやAPIとのやり取りでは Backed Enum が非常に便利です。保存時は .value を使い、取り出し時は from() / tryFrom() で安全に変換できます。
Enumにメソッドを定義する
Enumはクラスのようにメソッドやインターフェースを持てます。
<?php
enum Suit: string
{
case Hearts = 'H';
case Diamonds = 'D';
case Clubs = 'C';
case Spades = 'S';
public function label(): string
{
return match ($this) {
Suit::Hearts => 'ハート',
Suit::Diamonds => 'ダイヤ',
Suit::Clubs => 'クラブ',
Suit::Spades => 'スペード',
};
}
public function isRed(): bool
{
return match ($this) {
Suit::Hearts, Suit::Diamonds => true,
default => false,
};
}
}
$suit = Suit::Hearts;
echo $suit->label(); // ハート
var_dump($suit->isRed()); // bool(true)
echo $suit->value; // H
ロジックをEnum自身にまとめることで、match式やif文が散らばるのを防げます。
インターフェースを実装する
EnumはPHPのインターフェースを implements できます。
<?php
interface HasLabel
{
public function label(): string;
}
enum Status: int implements HasLabel
{
case Active = 1;
case Inactive = 0;
public function label(): string
{
return match ($this) {
Status::Active => '有効',
Status::Inactive => '無効',
};
}
}
function printLabel(HasLabel $item): void
{
echo $item->label() . PHP_EOL;
}
printLabel(Status::Active); // 有効
printLabel(Status::Inactive); // 無効
インターフェースを活用することで、Enumを既存の設計に自然に組み込めます。
全ケースの一覧取得
cases() メソッドを使うと全ケースの配列を取得できます。
<?php
enum Permission: string
{
case Read = 'read';
case Write = 'write';
case Delete = 'delete';
}
// 全ケースを列挙
foreach (Permission::cases() as $permission) {
echo "{$permission->name}: {$permission->value}" . PHP_EOL;
}
// Read: read
// Write: write
// Delete: delete
// selectボックス用の配列に変換する例
$options = array_map(
fn(Permission $p) => ['value' => $p->value, 'label' => $p->name],
Permission::cases()
);
フォームのセレクトボックスやAPIレスポンスの生成など、実際の開発でよく使うパターンです。
Enumを使う上での注意点
- Enumはインスタンス化できません(
newは使えない) - プロパティを持てません(定数
constは定義可能) - Pure Enumは
from()/tryFrom()が使えません - Backed Enumの値は
intかstringのみ(floatなどは不可)
<?php
enum Season
{
case Spring;
case Summer;
case Autumn;
case Winter;
// constは定義できる
const WARM_SEASONS = [self::Spring, self::Summer];
}
var_dump(Season::WARM_SEASONS);
// array(2) { [0]=> enum(Season::Spring) [1]=> enum(Season::Summer) }
まとめ
| 種類 | 値の有無 | from/tryFrom | 用途 |
|---|---|---|---|
| Pure Enum | なし | 使えない | 単純な区分け |
| Backed Enum (string) | 文字列 | 使える | DB・API連携 |
| Backed Enum (int) | 整数 | 使える | フラグ・コード管理 |
PHPのEnumを使うと、コードの意図が明確になり、不正な値が混入するバグを型レベルで防げます。match式との相性も抜群なので、ステータス管理やカテゴリ分けが必要な場面でぜひ活用してみてください。