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の出番です。

visitor@sai: /blog
  
   ██████╗  █████╗ ██╗
  ██╔════╝ ██╔══██╗██║
  ╚█████╗  ███████║██║
   ╚═══██╗ ██╔══██║██║
  ██████╔╝ ██║  ██║██║
  ╚═════╝  ╚═╝  ╚═╝╚═╝
    株式会社 才 (SAI Inc.)

  --------------------------------------------------
  
  ██╗    ██╗  ███████╗  ██╗       ██████╗   ██████╗    ███╗   ███╗  ███████╗
  ██║    ██║  ██╔════╝  ██║      ██╔════╝  ██╔════██╗  ████╗ ████║  ██╔════╝
  ██║ █╗ ██║  █████╗    ██║      ██║       ██║    ██║  ██╔████╔██║  █████╗
  ██║███╗██║  ██╔══╝    ██║      ██║       ██║    ██║  ██║╚██╔╝██║  ██╔══╝
  ╚███╔███╔╝  ███████╗  ███████╗  ╚██████╗  ╚██████╔╝  ██║ ╚═╝ ██║  ███████╗
   ╚══╝╚══╝   ╚══════╝  ╚══════╝   ╚═════╝   ╚═════╝   ╚═╝     ╚═╝  ╚══════╝

  Type 'help' to see available commands.
  Type 'gui'  to return to visual mode.
  --------------------------------------------------
visitor@sai:/blog$ cat enum-vs-const
── LaravelでEnumとConst、どう使い分ける? ──

PHP 8.1でEnumが導入されてから、「これまでconstで定義していたものを全部Enumに置き換えるべき?」という質問をよくいただきます。

結論から言うと、全部置き換える必要はないです。それぞれに得意な場面があります。

## constが向いているケース
設定値や閾値のように「ただの固定値」であれば、constで十分です。
FEE_RATE、FREE_SHIPPING_THRESHOLD、MAX_RETRYなど。
これらは「選択肢」ではなく「設定値」。型で守る必要はありません。

## Enumが向いているケース
Enumが真価を発揮するのは「状態」や「分類」を表現するとき。
constとの決定的な違いは、Enumは振る舞いを持てること。
ラベル変換やフラグ判定をEnum自身に閉じ込めることで、if文の散乱を防げます。

## Laravelとの相性
LaravelはEnum対応が手厚く、モデルのcastsにそのまま書けます。
バリデーションルールでも直接使えます。

## まとめ
- const:設定値、閾値、マジックナンバーの名前付け。「いくつ?」に答えるもの
- Enum:状態、分類、選択肢。「どれ?」に答えるもの。振る舞いを持たせたいとき

迷ったら「この値にメソッドを生やしたくなるか?」と考えてみてください。Yesなら、それはEnumの出番です。

Tech Stack: Laravel, PHP
visitor@sai:/blog