norotaro/enumaton
Enumaton is a Laravel package that streamlines working with PHP enums. It adds convenient helpers and integrations for enum casting, validation, and value handling, helping developers use enums consistently across models, forms, and APIs.
norotaro/enumata is a small utility package that layers convenience behaviour on top of native PHP 8.1+ backed enums — the kind of thing you reach for when your app/Enums directory starts accumulating hand-rolled label(), values(), and options() methods in every enum class.
Install
composer require norotaro/enumata
No service provider registration is required (the package is auto-discovered), and there is no migration or publish step for basic use. If the repo ships a config file, publish it only if you need to override defaults:
php artisan vendor:publish --tag=enumata-config
Where to look first
README.md — the authoritative API surface. Enum helper packages vary a lot in naming (label() vs description(), toArray() vs options()), so confirm method names against the version you installed rather than assuming.composer.json in the package — this is the file that matters most for v2.1.0, since the release bumped both the Laravel and PHP constraints.src/ — the package is small enough to read end-to-end in ten minutes, which is the fastest way to understand extension points.First use case
The highest-value entry point is almost always form dropdowns. Take an existing enum:
enum Status: string
{
case Draft = 'draft';
case Published = 'published';
case Archived = 'archived';
}
and add the package's trait (or extend its base enum, depending on which API the package exposes) so you get a key/value map for Blade::select or a Rule::enum() companion in one line instead of a bespoke static method. Once that compiles, the same trait typically covers validation, API resources, and factory defaults — so the first working dropdown usually justifies adoption on its own.
Treat enums as the single source of truth for the value set. The pattern that pays off is defining the enum once and deriving everything — validation rules, casts, form options, API payloads — from it. If a controller hardcodes ['draft', 'published', 'archived'] alongside an enum, you have two sources of truth and the package is not earning its keep.
Model casts. Native Laravel already handles this without any package, and you should keep using it:
protected $casts = [
'status' => Status::class,
];
Do not wrap casts in package helpers — the native cast is more predictable and better supported by tooling.
Validation. Pair the package's value list with Laravel's built-in rule so the two can never drift:
$request->validate([
'status' => ['required', Rule::enum(Status::class)],
]);
If the package exposes its own rule object, prefer Rule::enum() unless the package version adds something you specifically need (case-insensitive matching, for example).
Presentation layer separation. Keep human-readable labels — especially any that will be translated — out of the enum where possible, or at minimum route them through __() inside the enum method rather than returning raw English strings. Enums get serialised into API responses and queue payloads more often than people expect, and embedded display strings leak into those contexts.
Filament / Nova / Livewire. Enum option maps are the primary consumer here. Wire the package's options method directly into select fields so adding a case to the enum automatically appears in every admin form. This is the integration tip with the best effort-to-payoff ratio.
API resources. Be deliberate about ->value vs the case itself. $model->status->value for a stable wire format, or the case name if you want a more semantic contract — but pick one and apply it consistently, because changing it later is a breaking change for your API consumers.
v2.1.0 is a compatibility release, not a feature release. The changelog lists Laravel 12 support and a PHP version support update. There are no new features, deprecations, or documented breaking changes. Practically:
composer.json in the installed version; if your CI matrix or a legacy service still runs PHP 8.1, composer update will fail or silently pin you to v2.0.1.composer why-not norotaro/enumata 2.1.0
Lock file drift across a monorepo. In multi-app repos, one app can resolve v2.1.0 while another stays on v2.0.1 depending on its Laravel constraint. That is fine functionally, but it makes enum helper behaviour inconsistent across services — pin explicitly if that matters to you.
Native enum serialisation surprises. Enums in $casts serialise to their value in toArray()/JSON, but a raw enum passed to json_encode or stuffed into a queue payload without a cast will not. SerializesModels handles models, not loose enum properties on jobs. Convert explicitly at the boundary.
Rule::enum() and nullable fields. Rule::enum() fails on null. Add 'nullable' before it, or use Rule::enum(...)->when() style conditionals — a very common first-day bug.
Extension points. If the trait's default label generation (typically Str::headline() of the case name) does not match your product's wording, override the method in the enum rather than forking the package. Overriding per-enum beats a global config override, because label wording is rarely uniform across domains.
Debugging. When an option map looks wrong, dump the enum directly — Status::cases() — before suspecting the package. Nearly every issue in this category traces to a stale opcache, a cached config (php artisan config:clear), or a case whose backing value collides with another.
Version pinning advice. Given the package is small and the API surface is narrow, pin to ^2.1 and let patch releases float; the risk of an unexpected break is low, and Laravel 12 compatibility means you are unlikely to need anything older.
How can I help you explore Laravel packages today?