1. Qiita
  2. 投稿
  3. PHP

PHPで列挙型(enum)を作る

  • 186
    いいね
  • 3
    コメント

列挙型 - Wikipedia

まず列挙型の定義は〜となるんだけど、ここでは「あらかじめ定義した値のいずれかしか取らない特殊な型」という感じを想定してます。
要はSplEnumみたいなのですが、拡張モジュールの力を借りなくても、PHPだけで作れます。リフレクションを使うだけ。

<?php
abstract class Enum
{
    private $scalar;

    public function __construct($value)
    {
        $ref = new ReflectionObject($this);
        $consts = $ref->getConstants();
        if (! in_array($value, $consts, true)) {
            throw new InvalidArgumentException;
        }

        $this->scalar = $value;
    }

    final public static function __callStatic($label, $args)
    {
        $class = get_called_class();
        $const = constant("$class::$label");
        return new $class($const);
    }

    //元の値を取り出すメソッド。
    //メソッド名は好みのものに変更どうぞ
    final public function valueOf()
    {
        return $this->scalar;
    }

    final public function __toString()
    {
        return (string)$this->scalar;
    }
}
使い方
<?php
// トランプのスート型を定義する。4種類しか値を取らない。
// Enumをextendして、定数をセット
final class Suit extends Enum
{
  const SPADE = 'spade';
  const HEART = 'heart';
  const CLUB = 'club';
  const DIAMOND = 'diamond';
}

//インスタンス化
$suit = new Suit(Suit::SPADE);
echo $suit; //toString実装済みなので文字列キャスト可能

echo $suit->valueOf(); //生の値を取り出す。intやfloat等の場合に。

// 適当な値を突っ込もうとすると、InvalidArgumentExceptionが発生して停止
//$suit = new Suit('uso800');



//__callStaticを定義してあるのでnewを使わずこんな感じでも書ける(PHP5.3以降)
$suit = Suit::SPADE();

PHPには組み込みのEnum型はないので、無理にEnumを作った所で速度的な旨味はありません。ただ、型チェックだけで「この定義済みの値のいずれかである」ことが保証できます。

ユーザーの入力なんかを予め検証して、適当な型にキャストしておけば、以降は型チェックだけで安心してデータを扱えるようになります。べんり。

<?php

function doSomething(Suit $suit) {
  //Suitというタイプヒントによって、
  //$suitは必ず4種類のうちのどれかだと保証されている

}

元の値を取り出すメソッド名に困ったので、JavaScript風にvalueOf()にしてますが、まあ別に何でもOKです。