search
LoginSignup
24

posted at

updated at

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パッケージを使ってたけど乗り換えて良さそう。

参考

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
24