Laravel-enumの使い方

## はじめに

RailsでEnumを使っての開発に慣れてしまっていて、Laravelでも使いたかったので調べてみた。

## 環境

* PHP7.1
* Laravel5.6

## 1. enumとは

[Wikipedia](https://ja.wikipedia.org/wiki/%E5%88%97%E6%8C%99%E5%9E%8B)から以下抜粋
> 列挙型（れっきょがた、enumerated type）とは、コンピュータプログラミングにおいて、プログラマが選んだ各々の識別子をそのまま有限集合として持つ抽象データ型である。列挙型は一般に、カードのスートのように番号順を持たないカテゴリ変数として使われるが、実際のコンパイル時あるいは実行時には、列挙型は整数で実装されることが多い。各々の識別子は通例異なる整数値を持つが、複数の識別子に対して意図的に同じ整数値を割り当てる（つまり別名を定義する）ことも可能である。

> また列挙型は、整数を使用する場合と比較して、明示的にマジックナンバーを使用するよりもプログラムソースの可読性を改善するのに役立つ。言語によっては、列挙型の整数表現はプログラマに見えないようになっていることもあり、これによりプログラマが列挙値に対して算術演算を行うような乱用を防いでいる。

> 言語によっては、真偽値の論理型は、あらかじめ宣言された二値の列挙型とされている。

例えば、`公開`、`非公開`みたいなフラグを`boolean`型で定義したとします。
実際にDBに格納される値は`0`か`1`だったときに、文字列としては、`公開`、`非公開`を扱いたい場合などにenumはとても便利です。


## 2. パッケージ

Laravelにはenumを扱えるパッケージが二つありました。


パッケージ | githubスター数 | 情報量  
------- | ------------- | -----  
[laravel-enum](https://github.com/BenSampo/laravel-enum) | 71 | そんなにない
[laravel-enums](https://github.com/nasyrov/laravel-enums) | 24 | そんなにない

上記を見る限り大差はないように見受けられました。

ドキュメントを見た感じ、前者の`laravel-enum`の方がわかりやすかったので、そちらを採用しました。

## 3. 導入

```
$ composer require bensampo/laravel-enum
```

composerでインストールしたら、`php artisan make:enum`コマンドが使えるようになります。

## 4. 使ってみる

上の例でもあげたように`公開`、`非公開`用のenumを作成していこうと思います。

```
$ php artisan make:enum PublishStateType
```

以上を実行すると`app`ディレクトリ配下に`Enums`ディレクトリが作成され、その中に`PublishStateType.php`が生成されます。

`PublishStateType.php`を見てみると以下のようになっている

```php
<?php

namespace App\Enums;

use BenSampo\Enum\Enum;

final class PublishStateType extends Enum
{
    const OptionOne = 0;
    const OptionTwo = 1;
    const OptionThree = 2;

    /**
     * Get the description for an enum value
     *
     * @param $value
     * @return string
     */
    public static function getDescription($value): string
    {
        if ($value === self::OptionOne) {
            return 'Option one';
        }

        return parent::getDescription($value);
    }
}
```

を以下のようにします。

```php
<?php

namespace App\Enums;

use BenSampo\Enum\Enum;

final class PublishStateType extends Enum
{
    const Private = 0;
    const Public = 1;

    /**
     * Get the description for an enum value
     *
     * @param $value
     * @return string
     */
    public static function getDescription($value): string
    {
        switch ($value){
            case self::Private:
                return '非公開';
                brake;
            case self::Public:
                return '公開';
                brake;
            default:
                return self::getKey($value);
        }
    }
}
```

以上で`PublishStateType`の設定は一旦OKです。

## 5. コントローラーで使う

```php
use App\Enums\PublishStateType;
```

をコントローラーの上部へ記述し、

```
PublishStateType::getDescription('0'); // 非公開
PublishStateType::getDescription('1'); // 公開
```

のように扱えます。

## 6. ビューで使う

ビューで使う場合は、フルパスで記述をして使います。

```php
<p>{{\App\Enums\PublishStateType::getDescription('0')}}</p> // 非公開
<p>{{\App\Enums\PublishStateType::getDescription('1')}}</p> // 公開
```

となります。

## 7. getValueをカスタマイズする

getValueという定義されたメソッドを使えば、定数で定義したキーを引数に入れることで定数の値を取得することが出来る。

```php
<p>{{\App\Enums\PublishStateType::getValue('Private')}}</p> // 0
<p>{{\App\Enums\PublishStateType::getValue('Public')}}</p> // 1
```

しかし、やりたかったことは、
`Private`、`Public`ではなく、`公開`、`非公開`という文字列から定数の値を取得したかった

そこで`getValue`メソッドをカスタマイズする。
`PublishStateType.php`を開き以下のようにする

```php
<?php

namespace App\Enums;

use BenSampo\Enum\Enum;

final class PublishStateType extends Enum
{
    const Private = 0;
    const Public = 1;

    /**
     * Get the description for an enum value
     *
     * @param $value
     * @return string
     */
    public static function getDescription($value): string
    {
        switch ($value){
            case self::Private:
                return '非公開';
                brake;
            case self::Public:
                return '公開';
                brake;
            default:
                return self::getKey($value);
        }
    }
    
    public static function getValue(string $key)
    {
        switch ($key){
            case '非公開':
                return 0;
            case '公開':
                return 1;
            default:
                return parent::getValue($key);
        }
    }
}
```

```php
<p>{{\App\Enums\PublishStateType::getValue('非公開')}}</p> // 0
<p>{{\App\Enums\PublishStateType::getValue('公開')}}</p> // 1
```

`public static function getvalue`でオーバーライドして、`非公開`という文字列ならば`0`を返し、`公開`なら`1`を返すということを実現出来る。