23

投稿日

更新日

PHP 8.1 Enums を使ってみる

列挙型(Enumerations)

PHP8.1で実装されたEnumの使い方を軽くご紹介します。

環境

$ php -v
PHP 8.1.1 (cli) (built: Dec 17 2021 23:49:52) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.1, Copyright (c) Zend Technologies
    with Zend OPcache v8.1.1, Copyright (c), by Zend Technologies

使い方

<?php declare(strict_types=1);

enum AccountStatus
{
    case Active;
    case Inactive;
    case Leave;
}

var_dump(AccountStatus::Active); // enum(AccountStatus::Active)
var_dump(AccountStatus::Active->name); // string(6) "Active"
var_dump(AccountStatus::cases());
// array(3) {
//   [0]=>
//   enum(AccountStatus::Active)
//   [1]=>
//   enum(AccountStatus::Inactive)
//   [2]=>
//   enum(AccountStatus::Leave)
// }

enum と宣言して列挙型を宣言する。
case を使って列挙していく。大文字も小文字も使える

AccountStatus::Active とするとenumのインスタンスができる。
インスタンスの->nameプロパティへアクセスするとcaseの値を取得できる。
cases() でenum値の一覧を取得できます。

<?php declare(strict_types=1);

enum AccountStatus: string
{
    case ACTIVE = 'active';
    case INACTIVE = 'inactive';
    case LEAVE = 'leave';

    /**
     * @return string
     */
    public function description(): string
    {
        return match($this) {
            self::ACTIVE => '有効',
            self::INACTIVE => '無効',
            self::LEAVE => '退会済み',
        };
    }
}

var_dump(AccountStatus::ACTIVE); // enum(AccountStatus::ACTIVE)
var_dump(AccountStatus::ACTIVE->name); // string(6) "ACTIVE"
var_dump(AccountStatus::ACTIVE->value); // string(6) "active"
var_dump(AccountStatus::from('active')); // enum(AccountStatus::ACTIVE)
// var_dump(AccountStatus::from('undefined status')); // PHP Fatal error:  Uncaught ValueError
var_dump(AccountStatus::tryFrom('active')); // enum(AccountStatus::ACTIVE)
var_dump(AccountStatus::tryFrom('undefined status')); // NULL
var_dump(AccountStatus::ACTIVE->description()); // string(6) "有効"
var_dump(AccountStatus::LEAVE->description()); // string(12) "退会済み"
var_dump(AccountStatus::cases());
// array(3) {
//   [0]=>
//   enum(AccountStatus::Active)
//   [1]=>
//   enum(AccountStatus::Inactive)
//   [2]=>
//   enum(AccountStatus::Leave)
// }

列挙型はスカラー値情報をデフォルトでは持ってませんが、スカラー値を持つcase(Backed Case)を定義できます。
intまたはstringのスカラー値をサポートしてます。

Backed Enumは内部的にBacked Enumインターフェースを実装しています。
from($value)tryFrom($value) でスカラー値からEnumのcaseを返します。

<?php declare(strict_types=1);

final class Account
{
    public function __construct(
        private AccountStatus $accountStatus,
    ) {
    }
}

$account = new Account(AccountStatus::Active);
$account = new Account('undefined status');
// Fatal error: Uncaught TypeError: Account::__construct(): ...

他のクラスのコンストラクタで列挙型を型宣言して受け取れる。
未定義の値を渡すと型エラーが発生するので不正な値が入ることを防いでくれる。安心。

Enumとクラスの違い

  • 状態を持つことが禁止
  • コンストラクタやデストラクタは禁止
  • 継承は禁止
  • プロパティを持つことは禁止
  • public, private, protected メソッド は利用可能
  • public, private, protected な static メソッド は利用可能
  • public, private, protected な定数 は利用可能
  • インターフェースの実装 は利用可能
  • マジックメソッド __call, __callStatic, __invoke は利用可能。これ以外は禁止
  • マジック定数 __CLASS____FUNCTION__ は利用可能。これ以外は禁止

感想

思ったより扱いやすそう!早く実務で使ってみたい。
ただ、インターフェース使ったEnumはいまいち実務で使うイメージができなかった。
今まではBenSampo/laravel-enumパッケージを使ってたけど乗り換えて良さそう。

参考

新規登録して、もっと便利にQiitaを使ってみよう

  1. あなたにマッチした記事をお届けします
  2. 便利な情報をあとで効率的に読み返せます
ログインすると使える機能について
23