Laravelで選択肢用のマスターテーブルを作るのやめませんか?
フォームのセレクトボックスやチェックボックス、ラジオボタン等の選択肢に使うために、データベースでマスターテーブルを作るって、よくあることだと思います。
でも使うのって結局選択肢と表示画面だけなんですよね。しかもマスターのみでデータとしては増えない。
コンフィグファイルに入れれば?ってのもありですが、無駄な定義増やしたくない。
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みたいなものだと思って下さい。
<?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ドキュメント
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を呼び出せます。
Class Coupon extends Model
{
public function getTargetLabelAttribute()
{
return CouponTarget::from($this->target)->label();
}
}
色々なところで便利に使えるはずです。
Discussion
丁度、私も同じような事をやっていました。
最後の所の別解としては、Enum Casting を使うのも楽でいいかもですね。
こんにちは。
これは見逃していました。
(人''▽`)ありがとうです☆