このエントリはPHP Advent Calendar 2013 – Qiitaの25日目です。

Enumを作りました。GitHubに置いてあります。satooshi/ValueObject。参考にしたのはC#のEnum。未実装の部分もありますが、よく使いそうなメソッドは実装しました。

Enum

名前はValueObjectになってますが、欲しかったのはEnumの方です。こんな風にして使います。例えば性別や既婚・独身みたいなステータス。

<?php
use Satooshi\Component\Enum\Enum;
use Satooshi\Component\Enum\EnumValueObject;
/**
* @method isMale()
* @method isFemale()
*/
final class Gender implements EnumValueObject
{
use Enum;
const MALE = 'M';
const FEMALE = 'F';
}
/**
* @method isSingle()
* @method isMarried()
*/
final class MaritalStatus implements EnumValueObject
{
use Enum;
const SINGLE = 1;
const MARRIED = 2;
}

Enumというと連番を想像しますが、文字列でも値を定義できます。むしろ連番定数を定義したい、とは思いますが、定数を定義しつつ自動的に定数値を割り当てるには、自動生成するしかない気がします。Settyの方法がおそらくそういうやり方なんじゃないかと。

Flags attribute

Enumの中でも、排他的な値ではなく、同時に複数の値を持てるような場合、.NETではFlagsという属性を付ける事ができます(だったはず)。PHPでもエラーレベルの指定方法で、こういった定数が使用されてますね。

例えば、フォントの指定方法として、

  • 下線
  • イタリック
  • ボールド

などがあったとします。これらはすべて同時に指定可能、あるいは指定なしだったとすると、

<?php
use Satooshi\Component\Flags\Flags;
use Satooshi\Component\Flags\FlagsValueObject;
final class FontStyle implements FlagsValueObject
{
use Flags;
const NONE = 0;
const UNDER_LINE = 1;
const ITALIC = 2;
const BOLD = 4;
}

こんなクラスを作ることができます。

<?php
// 定数を使う
$underLineAndBold = FontStyle::createFlags(FontStyle::UNDER_LINE | FontStyle::BOLD);
// またはインスタンスから
$underLine = FontStyle::createUnderLine();
$bold = FontStyle::createBold();
// $underLine | $bold と書きたいが、、
$underLineAndBold = FontStyle::createFlags($underLine() | $bold());
echo $underLineAndBold->getValue(); // 5

use case

Symfony2アプリケーションで使う場面はこんな感じ。

  1. Formのchoiceフィールドとして使う(値と名前の組)
  2. Twigテンプレートで名前を表示する
  3. DoctrineでDBに永続化する

Form

getOptions()で[名前 => 値]の配列が取得できるので、[値 => 名前]にすると、そのままformオプションに使えます。

Twig

個別の列挙値の名前が必要であれば、インスタンスに対してgetName()を呼べば定数の名前が返ってきます。あるいはgetReadable()みたいなメソッドを個別に実装してもいいですし、多言語対応アプリの場合はtranslatorを使ってもいいですね。

Doctrine

定数値がstringならtype="string"、intならtype="int"とすると、永続化する際には使えるかもしれません(未確認)。しかし、ロードしたタイミングでEnumオブジェクトが出来上がって欲しいので、これは何かしら作らないとダメそう。

まとめ

GitHubでenumを検索してみると、PHPの実装は現在49個あるらしいです。早くPHPにもenumが実装されるといいですね。

ホーチミンは30度のクリスマスでした。それでは。

Merry Christmas and a Happy New Year.