🤭

Laravelで選択肢用のマスターテーブルを作るのやめませんか?

2024/01/11に公開2

フォームのセレクトボックスやチェックボックス、ラジオボタン等の選択肢に使うために、データベースでマスターテーブルを作るって、よくあることだと思います。
でも使うのって結局選択肢と表示画面だけなんですよね。しかもマスターのみでデータとしては増えない。
コンフィグファイルに入れれば?ってのもありですが、無駄な定義増やしたくない。

PHP8.1から、Enumが使えるようになり、定義を列挙することができるようになりました。
もちろんLaravelでも使用可能です。
選択肢に応じて、Enumの定義を増やせばいいんです。
まずはLaravelをインストールしていることが前提です。

Appの中にEnumsディレクトリを作ろう

Appフォルダの中にEnumsという名前でフォルダを作成します。
このなかに色んなファイルを入れていきます。

Enumsディレクトリの中にファイルを作成する

今回はクーポンというものを作っている前提で、クーポンのターゲットの選択肢用のファイルを作成します。
Enumsの中に、CouponTarget.phpという名称で、手動でphpファイルを作成します。

CouponTargetクラスの内容

作りたい選択肢は3つ。
・全員(ALL)1
・新規様(BEGINNER)2
・常連様(REPEATER)3

そしてこの3つの選択肢に数字を割り当てます。データベースで言うIDみたいなものだと思って下さい。

Enums\CouponTarget.php

<?php
namespace App\Enums;

enum CouponTarget: int
{
    case ALL = 1;
    case BEGINNER = 2;
    case REPEATER = 3;
}

formで呼び出した時のLabel名を付ける

表示した時に、全員とか新規様等の名前を見せたいので、各caseに名前を付けていきます。
ここで便利なのが、PHP8から使えるようになったmatch()関数を使用します。

match
(PHP 8)
match 式は、値の一致をチェックした結果に基づいて評価結果を分岐します。 switch 文と似ていますが、 match 式は複数の候補と比較される制約式を持ちます。 switch 文とは異なり、 三項演算子のように値を評価します。 switch 文とは異なり、 弱い比較(==)ではなく、 型と値の一致チェック(===) に基づいて行われます。 match 式は PHP 8.0.0 以降で利用可能です
PHPドキュメント

Enums\CouponTarget.php
public function label() : string
{
        return match($this)
        {
	    CouponTarget::ALL => '全員',
            CouponTarget::BEGINNER => '新規様',
            CouponTarget::REPEATER => '常連様',
        };
}

これにより、caseの文字列がmatchしたら,labelの文字列が返るようになります。

Bladeで使いたいとき

formのselectで選択肢に入れたいときは、次のように使用します。

<select name="target">
    <option value="">選択してください</option>
    @foreach (\App\Enums\CouponTarget::cases() as $target)
        <option value="{{ $target->value }}">{{ $target->label() }}</option>
    @endforeach
</select>

選択したものを表示したいとき。
今回は、選択されたデータは、Couponモデル、couponsテーブルのtargetカラムに格納してあります。
CouponモデルにAttributeを作って表示を簡単にしちゃいましょう。
Enumに作ったCouponTargetのlabelを呼び出せます。

Models\Coupon.php
Class Coupon extends Model 
{
    public function getTargetLabelAttribute()
    {
        return CouponTarget::from($this->target)->label();
    }
}

色々なところで便利に使えるはずです。

Discussion