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

Laravel Enums Laravel Package

nasyrov/laravel-enums

Laravel Enums adds first-class enumeration support: define typed enum classes, then use them as Eloquent casts, validation rules, and translatable labels. Helpers for values, options, and comparisons make model attributes and form choices safer and more expressive.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and verify compatibility first. The package's last release was December 2020, and it has a small maintenance footprint (32 stars). Before writing any code, confirm two things in a scratch project:

  1. composer require nasyrov/laravel-enums resolves on your Laravel/PHP version.
  2. The README's example class actually runs (php artisan tinker), because API naming in small packages drifts from docs.

If it won't install cleanly on Laravel 9+ or PHP 8.1+, stop here and use native PHP enums instead — see Gotchas.

Where to look first, in order:

  • README.md — the canonical API surface; copy its example verbatim rather than guessing method names.
  • src/ — usually a small set of files: the base Enum class, an exception, and possibly a validation rule or service provider. Skim these; the whole package is likely <500 lines.
  • composer.json — check the require constraints (illuminate/* version) and whether a service provider is auto-discovered.

First use case — model an order status:

// app/Enums/OrderStatus.php
namespace App\Enums;

use Nasyrov\Laravel\Enums\Enum; // verify namespace from README

final class OrderStatus extends Enum
{
    public const PENDING   = 0;
    public const PAID      = 1;
    public const SHIPPED   = 2;
    public const CANCELLED = 3;
}

Then use the constants directly in your domain code — that alone is the 80% value:

$order->status = OrderStatus::PAID;

if ($order->status === OrderStatus::SHIPPED) {
    // ...
}

Once OrderStatus::PAID reads well in your models and controllers, layer on the package's helper methods (labels, lists, validation) as needed.

Implementation Patterns

Constants as the source of truth. The most robust pattern is to treat the enum class as a set of named integer/string constants and let the package's helpers be sugar on top. Keep enum classes final so nobody subclasses and adds a status you didn't intend.

Select dropdowns / API payloads. Enum packages exist largely to solve "give me an array of value => label for a form." The typical call is a static method like toArray() / toSelectArray() / getValues(), and a per-constant label method you override:

final class OrderStatus extends Enum
{
    public const PENDING = 0;
    public const PAID    = 1;

    public static function labels(): array
    {
        return [
            self::PENDING => 'Awaiting payment',
            self::PAID    => 'Paid',
        ];
    }
}

Pass that array straight to a Blade @foreach or a FormRequest in: rule. Check the README for the exact method contract — some versions expect descriptions(), labels(), or an overridden getDescription($value); wire your labels to whichever the base class calls.

Validation. Wrap enum values in a validation rule so requests can't submit an off-list status:

$request->validate([
    'status' => ['required', Rule::in(OrderStatus::getValues())],
]);

Or, if the package ships an enum rule class, prefer it — it keeps the allowed set defined in one place. Verify the rule's namespace in src/.

Eloquent casts (use with care). Many enum packages support attribute casting so $order->status returns an enum wrapper instead of a raw int:

protected $casts = [
    'status' => OrderStatus::class,
];

This is convenient but invasive: it changes === semantics (enum object vs. int), affects JSON serialization, and complicates query building (where('status', OrderStatus::PAID) may or may not work transparently). If you adopt it, do so consistently across the model and write a test asserting both the comparison and the toArray()/toJson() output.

Comparison helpers. If the package offers is(), isNot(), or equals(), use them only when you're already holding an enum instance; otherwise stick to strict === against the constant. Mixing both styles in one codebase is the fastest path to a subtle bug.

Integration tips:

  • Reference enum constants in migrations' default() and in seeders rather than magic numbers (->default(OrderStatus::PENDING)).
  • For API responses, expose labels via an accessor or API resource rather than leaking raw integers and hoping the frontend knows the mapping.
  • Co-locate enums under app/Enums and add a tests/Unit/Enums/*Test.php asserting that every constant appears in your labels array — a cheap guard against adding a status and forgetting its display string.

Gotchas and Tips

The big one: this package predates PHP 8.1 enums and Laravel 9's native enum support. The last release was 2020-12-29; PHP 8.1 (Nov 2021) introduced first-class enum, and Laravel added native enum casting and Rule::enum() shortly after. For any new project, or any project on PHP 8.1+, use native enums:

enum OrderStatus: int
{
    case Pending = 0;
    case Paid = 1;

    public function label(): string { /* match() */ }
}

You get backed-enum casting in Eloquent, Rule::enum(OrderStatus::class), exhaustive match, and static analysis support — all without a third-party dependency. Treat nasyrov/laravel-enums as something you inherit on a legacy codebase, not something you adopt.

No BackedEnum interoperability. Because it's constant-based, instances won't satisfy BackedEnum type hints, won't work with match (true)-style backed-enum tooling, and PHPStan/Psalm coverage is manual. Budget time if you later migrate.

Version-constraint hell. A 2020 package likely constrains illuminate/support to ^6|^7|^8 (or narrower). On Laravel 10/11 you'll hit dependency resolution errors or need --ignore-platform-reqs / a fork. Forks mean you own the maintenance — check whether the base class does anything you can't replicate in ~40 lines.

Cast round-trip surprises. Enum casts can return a wrapper object where the database returns an int. $order->getRawOriginal('status') still gives the raw value; $order->status may give the object. Assert equality with the constant ($order->status == OrderStatus::PAID vs ===) deliberately, and check what happens on an out-of-range value — some enum casts throw, some return the raw scalar. Test the invalid path explicitly.

Strict comparison with casts. Once casting is on, OrderStatus::PAID === $order->status can silently fail if the cast returns an object rather than an int. Prefer ->is(OrderStatus::PAID) if the package provides it, or $order->status->value === OrderStatus::PAID if the wrapper exposes the raw value.

Config caching and auto-discovery. If the package registers a service provider, run php artisan config:clear && php artisan package:discover after install. A stale bootstrap/cache/packages.php is a common reason the enum helpers "don't exist" in a deployed environment but work locally.

Extension points. Because the surface is small, subclassing the base — overriding the label/description method or adding a forSelect() static — is usually the intended customization. Keep those overrides in one base class (App\Enums\Enum) rather than repeating them per enum, so a future migration to native enums only touches one file.

Debugging helper methods. When a static helper returns an unexpected shape, dd(OrderStatus::class::toArray()) in tinker and read the base class method it calls. With a package this small, the source is the documentation — there's rarely a layer of indirection you can't trace in two minutes.

Exit strategy. Pin the package version in composer.json, wrap usage behind your own app/Enums classes, and avoid spreading package-specific helper calls across views and controllers. When you migrate to PHP 8.1 native enums (or to a maintained alternative like bensampo/laravel-enum if you need richer features on older PHP), the blast radius stays confined to the enum classes themselves.

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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource