PHPのEnumでの検証
以下のようなEnumがあるとしたとき
enum Test: string
{
case Test1 = 'test1';
case Test2 = 'test2';
case Test3 = 'test3';
}
検証の際いちいち
if ($test === Test::Test1) {}
みたいなことを書くと可読性が悪くなる気がしたので
以下のようなトレイトを用意して
trait EnumIsTrait {
public static function tryFromName(string $name)
{
foreach (self::cases() as $case) {
if ($case->name === $name) {
return $case;
}
}
return null;
}
public function is(string $name)
{
return $this === self::tryFromName($name);
}
public function __call($calledName, $args)
{
preg_match('/^is([a-zA-Z0-9]+)$/', $calledName, $matches);
$caseName = $matches[1] ?? false;
if ($caseName) {
return $this->is($caseName);
}
throw new \Exception();
}
}
先ほどのEnumに実装すると
enum Test: string
{
use EnumIsTrait;
case Test1 = 'test1';
case Test2 = 'test2';
case Test3 = 'test3';
}
if ($test->isTest1()) { }
のような形で検証ができると思います。
関数の実態はないので、@method
などを定義しておくと良いと思います。
確認用コード
<?php
enum Test: string
{
use IsEnumTrait;
case Test1 = 'test1';
case Test2 = 'test2';
case Test3 = 'test3';
}
trait IsEnumTrait {
/**
* Enumの name から Enumを取得
*/
public static function tryFromName(string $name)
{
foreach (self::cases() as $case) {
if ($case->name === $name) {
return $case;
}
}
return null;
}
/**
* 現在のEnumが name のEnumかどうか検証
*/
public function is(string $name)
{
return $this === self::tryFromName($name);
}
public function __call($calledName, $args)
{
preg_match('/^is([a-zA-Z0-9]+)$/', $calledName, $matches);
$caseName = $matches[1] ?? false;
if ($caseName) {
return $this->is($caseName);
}
throw new \Exception();
}
}
var_dump(Test::Test1->isTest1());
var_dump(Test::Test2->isTest1());
// outputs
// bool(true)
// bool(false)
laravelのモデルのプロパティにEnumをセットして判定する際は
$casts = [];
でEnumへの変換を設定していると
$this->xxxx->is〇〇();
で判定できるので一行あたりが短く書けるかなと思いました。