LaravelでEnumとConst、どう使い分ける?
Laravel
PHP
PHP 8.1でEnumが導入されてから、「これまでconstで定義していたものを全部Enumに置き換えるべき?」と考えることがあると思います。
結論から言うと、全部置き換える必要はないです。それぞれに得意な場面があります。
constが向いているケース
設定値や閾値のように「ただの固定値」であれば、constで十分です。
class PaymentConfig
{
// 決済手数料率(3.6%)
const FEE_RATE = 0.036;
// 無料配送の最低金額
const FREE_SHIPPING_THRESHOLD = 5000;
// リトライ上限
const MAX_RETRY = 3;
}
これらは「選択肢」ではなく「設定値」です。FEE_RATEが0.036か0.05かは業務ルールの話であって、型で守る必要はありません。
Enumが向いているケース
一方、Enumが真価を発揮するのは「状態」や「分類」を表現するときです。
enum OrderStatus: string
{
case Pending = 'pending';
case Paid = 'paid';
case Shipped = 'shipped';
case Delivered = 'delivered';
case Cancelled = 'cancelled';
public function label(): string
{
return match($this) {
self::Pending => '注文受付',
self::Paid => '決済完了',
self::Shipped => '発送済み',
self::Delivered => '配達完了',
self::Cancelled => 'キャンセル',
};
}
public function isFinal(): bool
{
return in_array($this, [self::Delivered, self::Cancelled]);
}
}
constとの決定的な違いは、Enumは振る舞いを持てること。ラベル変換やフラグ判定をEnum自身に閉じ込めることで、if文の散乱を防げます。
Laravelとの相性
LaravelはEnum対応が非常に手厚く、モデルのcastsにそのまま書けます。
class Order extends Model
{
protected function casts(): array
{
return [
'status' => OrderStatus::class,
];
}
}
// DBには文字列 'pending' で保存、取得時は自動的にEnumへ
$order->status; // OrderStatus::Pending
$order->status->label(); // '注文受付'
$order->status->isFinal(); // false
バリデーションルールでも直接使えます。
use Illuminate\Validation\Rules\Enum;
$request->validate([
'status' => ['required', new Enum(OrderStatus::class)],
]);
まとめ
使い分けは意外とシンプルです。
- const:設定値、閾値、マジックナンバーの名前付け。「いくつ?」に答えるもの
- Enum:状態、分類、選択肢。「どれ?」に答えるもの。振る舞いを持たせたいとき
迷ったら「この値にメソッドを生やしたくなるか?」と考えてみてください。Yesなら、それはEnumの出番です。