Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Php Enum Utils Laravel Package

dive-be/php-enum-utils

Utilities for PHP 8.1+ enums in Laravel: convert enum cases to arrays, values, options, and labels for forms and APIs, compare and inspect cases, and cut boilerplate with a small, dependency-free helper set that makes working with native enums painless in everyday application code.

Deep Wiki
Context7

Getting Started

composer require dive-be/php-enum-utils

Requires PHP 8.1+ (native enums). There is no config file, no service provider to publish, no migrations — it's a trait library you use inside your own enums. Start by reading src/Concerns/ in the installed vendor directory (or the README); the whole package is a handful of traits and static helpers, so you can digest it in one sitting.

The first use case to wire up is the boring one you hit on every project: turning an enum into arrays for selects, validation, and API responses.

use Dive\EnumUtils\Concerns\EnumToArray;

enum OrderStatus: string
{
    use EnumToArray;

    case Pending = 'pending';
    case Paid    = 'paid';
    case Refunded = 'refunded';
}

OrderStatus::names();   // ['Pending', 'Paid', 'Refunded']
OrderStatus::values();  // ['pending', 'paid', 'refunded']
OrderStatus::toArray(); // ['Pending' => 'pending', ...]

Add the trait to your first enum, replace the hand-rolled const arrays or array_column(self::cases(), 'value') snippets scattered around the codebase, and you'll immediately see where the package earns its keep.

Implementation Patterns

Trait-per-enum, not inheritance. PHP enums can't extend, so the package's trait approach is the only sane way to share behaviour. Put EnumToArray on domain enums, and optionally EnumToAssoc (name => value map) where you need label/value pairs for a <select> or an Inertia prop.

Single source of truth for form options. Build one method (or enum) that feeds validation, Blade/Inertia, and factories:

// FormRequest
'status' => ['required', Rule::in(OrderStatus::values())],

// Blade / Inertia
<select>
  @foreach (OrderStatus::toArray() as $label => $value)
    <option value="{{ $value }}">{{ $label }}</option>
  @endforeach
</select>

Labels belong in the enum, not the trait. The package gives you names/values; add a label(): string match-expression method yourself and a EnumToArray::toArray() override (or a labels() helper) if you want human-readable names. Keeps translation (__('enums.status.paid')) close to the cases.

Wrap it in a base contract for consistency. Define interface HasValues {} and a shared trait alias so every enum in the app exposes the same API. Then a Blade component or a toSelectOptions() macro works uniformly.

Test data providers. OrderStatus::values() is the obvious source for PHPUnit/Pest #[DataProvider] methods; OrderStatus::names() for asserting that every case is handled by match statements:

it('handles every status', function (string $name) {
    expect(OrderStatus::fromName($name))->toBeInstanceOf(OrderStatus::class);
})->with(OrderStatus::names());

That "exhaustive match" test is the highest-value thing this package enables — it catches the enum case you added but forgot to handle in a match.

Factories, seeders, and API resources. Use values() with fake()->randomElement(...), and expose ->value in API resources. Keep the enum in the domain layer, serialize to the backed value at the boundary.

Comparison helpers. For code that filters collections or checks state transitions, enum_equals()-style helpers (or your own is()/in() methods) read better than $a === $b on enum instances, especially when you're comparing nullable enums. If the package's helper doesn't cover your case, wrap it once rather than scattering null checks.

Gotchas and Tips

  • Traits only work on enums. use EnumToArray; inside a normal class blows up at autoload/analysis time with a confusing error. If you want the same helpers on a non-enum, copy the methods to a separate class rather than trying to share the trait.
  • Reserved-method collisions. Native enums already reserve cases(), from(), tryFrom(). Don't define your own values() in the enum body and import the trait — fatal "trait method collision". If you need custom formatting, alias or override deliberately.
  • Unit vs backed enums. values() only makes sense for backed enums. On a pure (unit) enum you'll get names or an error depending on the helper — decide early whether your enum is persisted (backed) or just a state marker (unit).
  • toArray() is not JsonSerializable. Backed enums serialize as their ->value via json_encode()/Laravel's JSON responses, but a toArray() that produces ['Pending' => 'pending'] will be treated as a plain array. Don't assume the two paths line up; be explicit in JsonResources.
  • Case order matters. names()/values()/toArray() preserve declaration order. Sorting alphabetically or by business priority will change every dropdown and test expectation — do it once, consciously, or sort at the call site.
  • Name-based lookups need a fallback. fromName('Paid') will throw ValueError on a typo; reach for tryFromName() when parsing user input or API payloads. Prefer the backed value (OrderStatus::tryFrom($request->input('status'))) at HTTP boundaries.
  • Static analysis. If PHPStan/Psalm complains about the trait's return types or your IDE loses autocomplete, add @method static array values() docblocks on the enum or a stub file. The traits are generic-ish; older analysers need help.
  • No config, no cache. Nothing to publish, nothing to clear. If you find yourself in config/ looking for options, you're in the wrong package.
  • It's small and low-maintenance (31 stars, single vendor). That's a feature — but treat it as vendorable code. Pin the version, and if the repo stalls, copying three traits into App\Support\Enum is a ten-minute migration. Don't let it become load-bearing infrastructure.
  • Debugging enum failures. ValueError: "x" is not a valid backing value for enum Y almost always means a DB row, fixture, or API payload predates a case rename. Add a data-migration check or an assertion in the seeder using Y::values().
  • Don't call values() inside a loop. It's cheap, but Rule::in(...) inside foreach over 10k rows is wasted work; compute once and pass it in.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
ably/pubsub-server
mstfkhazaal/defender
mfonte/base62x
karnoweb/metapilot
tobya/bcsapiwrapper
swalker2/cpanel
vish4395/laravel-translation-manager
morningtrain/economic
teksite/systeminfo-laravel
atomcms/voting
run6/weather
siokas/laravelembeddirectives
adamlien/pkuuids
gilsonsouza/lara-doc-generator
manelgavalda/enrollment_mobile
unabomber/timezone
delatbabel/contacts
astritzeqiri/g-recaptcha
kevinongko/laravel-genode
developeruz/laravel-analytics