Search by

timezhero / enhanced-enums

TimeZHero

Enhanced enums for Laravel

Package info

github.com/TimeZHero/laravel-enhanced-enums

pkg:composer/timezhero/enhanced-enums

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 1

Open Issues: 0

v2.0.0 2026-11-14 13:15 UTC

This package is auto-updated.

Last update: 2026-11-14 13:17:38 UTC


README

A trait and two attributes that add labels, select lists, safe conversion and comparisons to PHP enums in Laravel applications.

Requirements

  • PHP 8.5+
  • Laravel 13.0+

Installation

Install the package via Composer:

composer require timezhero/enhanced-enums

Usage

Add the Enhancement trait to any enum:

<?php

namespace App\Enums;

use TimeZHero\EnhancedEnums\Enums\Traits\Enhancement;

enum OrderStatus: string
{
    use Enhancement;

    case Pending = 'pending';
    case Processing = 'processing';
    case Shipped = 'shipped';
    case Delivered = 'delivered';
    case Cancelled = 'cancelled';
}

Available Methods

  • values() — Get all enum values
  • names() — Get all enum case names
  • collect() — Get cases as a Laravel Collection
  • getLabel() — Get translated label for a case
  • toSelectList() — Generate key-value pairs for dropdowns
  • wrap() — Safely convert raw values to enum instances
  • is() — Check equality with another value
  • isNot() — Check inequality with another value
  • isIn() — Check if value is in a collection
  • isNotIn() — Check if value is not in a collection

values()

Get all enum values as an array:

OrderStatus::values();
// ['pending', 'processing', 'shipped', 'delivered', 'cancelled']

names()

Get all enum case names as an array:

OrderStatus::names();
// ['Pending', 'Processing', 'Shipped', 'Delivered', 'Cancelled']

collect()

Get all enum cases as a Laravel Collection:

OrderStatus::collect();
// Illuminate\Support\Collection containing all OrderStatus cases

Use the #[CollectedBy] attribute to specify a custom collection class:

<?php

namespace App\Enums;

use App\Collections\StatusCollection;
use TimeZHero\EnhancedEnums\Enums\Attributes\CollectedBy;
use TimeZHero\EnhancedEnums\Enums\Traits\Enhancement;

#[CollectedBy(StatusCollection::class)]
enum OrderStatus: string
{
    use Enhancement;

    case Pending = 'pending';
    case Processing = 'processing';
    // ...
}
OrderStatus::collect(); // Returns StatusCollection instance

getLabel()

Get a translated label for the enum case. Supports two translation strategies.

Keys strategy (default)

Translations are looked up at enums.{snake_case_class}.{value}:

// In lang/en/enums.php
return [
    'order_status' => [
        'pending' => 'Awaiting Confirmation',
        'processing' => 'Being Processed',
    ],
];
OrderStatus::Pending->getLabel(); // "Awaiting Confirmation"
OrderStatus::Shipped->getLabel(); // "Shipped" (no translation: the case name, headlined)

A case with no translation falls back to its headlined name (InReview becomes "In Review"), so the trait works without any translation file.

JSON strategy

Use the #[TranslationStrategy] attribute to translate the value itself through the JSON translation files:

<?php

namespace App\Enums;

use TimeZHero\EnhancedEnums\Enums\Attributes\TranslationStrategy;
use TimeZHero\EnhancedEnums\Enums\Traits\Enhancement;
use TimeZHero\EnhancedEnums\Enums\Translation;

#[TranslationStrategy(Translation::Json)]
enum PaymentMethod: string
{
    use Enhancement;

    case CreditCard = 'Credit Card';
    case BankTransfer = 'Bank Transfer';
    case PayPal = 'PayPal';
}
// In lang/it.json
{
    "Credit Card": "Carta di Credito",
    "Bank Transfer": "Bonifico Bancario"
}
PaymentMethod::CreditCard->getLabel(); // "Carta di Credito" (when locale is 'it')
PaymentMethod::PayPal->getLabel();     // "PayPal" (no translation: the value itself)

toSelectList()

Get labels keyed by value, in declaration order, for dropdowns and form selects:

OrderStatus::toSelectList();
// Collection: ['pending' => 'Awaiting Confirmation', 'processing' => 'Being Processed', 'shipped' => 'Shipped', ...]

The result is a plain Collection, so reorder it with ->sort() or ->sortKeys() when needed.

wrap()

Convert raw values to enum instances safely:

OrderStatus::wrap('pending');              // OrderStatus::Pending
OrderStatus::wrap(OrderStatus::Pending);   // OrderStatus::Pending (unchanged)
OrderStatus::wrap('invalid');              // null
OrderStatus::wrap(null);                   // null

A raw value matches a case when their string forms are identical: 3 and '3' are interchangeable, while '3.0', ' 3' and '03' match nothing. An int-backed enum given a non-numeric string returns null rather than throwing.

is()

Check equality with another enum case or raw value (raw values are matched as in wrap()):

$status = OrderStatus::Pending;

$status->is(OrderStatus::Pending);  // true
$status->is('pending');             // true
$status->is(OrderStatus::Shipped);  // false

isNot()

Check inequality with another enum case or raw value:

$status = OrderStatus::Pending;

$status->isNot(OrderStatus::Shipped);  // true
$status->isNot('pending');             // false

isIn()

Check if the value is in a collection of cases or raw values:

$status = OrderStatus::Pending;

$status->isIn([OrderStatus::Pending, OrderStatus::Processing]);  // true
$status->isIn(['shipped', 'delivered']);                         // false

isNotIn()

Check if the value is not in a collection of cases or raw values:

$status = OrderStatus::Pending;

$status->isNotIn(['shipped', 'delivered']);                         // true
$status->isNotIn([OrderStatus::Pending, OrderStatus::Processing]);  // false

Pure enums

The trait also works on enums without a backing type. The case name stands in wherever a value is needed:

enum Stage
{
    use Enhancement;

    case Draft;
    case InReview;
}

Stage::values();               // ['Draft', 'InReview']
Stage::wrap('InReview');       // Stage::InReview
Stage::Draft->is('Draft');     // true
Stage::InReview->getLabel();   // __('enums.stage.InReview'), or "In Review"

Development

composer test           # run the tests
composer test-coverage  # run the tests and require 100% coverage
composer lint           # fix code style with Laravel Pint
composer lint-check     # check code style without fixing

License

MIT