まず列挙型の定義は〜となるんだけど、ここでは「あらかじめ定義した値のいずれかしか取らない特殊な型」という感じを想定してます。
要は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です。