LoginSignup
363
329

More than 5 years have passed since last update.

PHPで列挙型(enum)を作る

Last updated at Posted at 2013-03-07

列挙型 - 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です。

363
329
3

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
  3. You can use dark theme
What you can do with signing up
363
329