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 Enumeration Laravel Package

sourceboat/laravel-enumeration

A Laravel package for defining and using enumerations in PHP, with support for validation rules, model casting, and comparing enum values in a clean, type-safe way across your application.

View on GitHub
Deep Wiki
Context7

Getting Started

1. Install and confirm it loads

composer require sourceboat/laravel-enumeration

Laravel's package auto-discovery should register the service provider. If the package ships a config file, publish it:

php artisan vendor:publish --provider="Sourceboat\LaravelEnumeration\LaravelEnumerationServiceProvider"

Check php artisan list — if the package exposes a generator (commonly make:enumeration or enum:make), it will show up there.

2. Where to look first

  • vendor/sourceboat/laravel-enumeration/src/ — the base enumeration class is the thing you will extend for every enum in your app. Read it before reading the README examples; most of the magic lives in inherited static methods.
  • The package is described as based on eloquent/enumeration, so also skim vendor/eloquent/enumeration/src/ for the underlying Enumerable / Enumeration interfaces. If a method on your enum seems "missing", it is probably inherited from that parent library.
  • The README for exact method names (toArray, values, keys, fromValue, etc.) — APIs of enumeration packages diverge in small but breaking ways, so copy signatures from the README rather than from memory of similar packages.

3. First use case: replace a class-constant + array lookup

The canonical day-one win is a status column that is currently guarded by an array of strings used in three places (migration default, validation rule, Blade select). Define one enum and delete the other three:

namespace App\Enums;

use Sourceboat\LaravelEnumeration\Enumeration;

class UserStatus extends Enumeration
{
    const ACTIVE    = 'active';
    const SUSPENDED = 'suspended';
    const DELETED   = 'deleted';
}

Then use it in a Rule::in, a <select>, and a model cast (see below). If that single refactor works end-to-end, the package is worth keeping; if it fights you, you have lost ten minutes.

Implementation Patterns

Model casts. The main reason to pick a Laravel-specific enumeration over a bare PHP one is attribute casting. Check the README for whether the package uses a Laravel Castable class or a legacy getXAttribute accessor pattern — the API differs between package versions, and this is the single most version-sensitive piece of code you will write.

class User extends Model
{
    protected $casts = [
        'status' => UserStatus::class,
    ];
}

$user->status;               // UserStatus instance (or constant value, depending on version)
UserStatus::ACTIVE;          // "active"

Validation. Expose the values once and reuse:

'status' => ['required', Rule::in(UserStatus::values())],

Wrapping this in a custom rule (EnumExists(UserStatus::class)) pays off the moment you have ten enums; it keeps controllers from importing every enum class.

Presentation / localization. Keep human labels next to the machine values, not in Blade conditionals:

public static function labels(): array
{
    return [
        self::ACTIVE    => __('Statuses.active'),
        self::SUSPENDED => __('Statuses.suspended'),
        self::DELETED   => __('Statuses.deleted'),
    ];
}

If the base class already provides a label/description hook, override it rather than adding a parallel static method — two competing label APIs in one codebase is a common rot pattern.

Form / API plumbing. Add one small presenter layer so the enum never leaks into Blade directly:

// App\Support\EnumOptions::for(UserStatus::class) => [['value' => 'active', 'label' => 'Active'], ...]

Query scopes and query building. Because values are plain scalars, where('status', UserStatus::ACTIVE) works with no cast overhead. For multi-status filters, add a scope that accepts an array of enum instances and maps to ->value/getValue() in one place — that mapping call is exactly the kind of thing that changes between enum package versions, so isolate it.

Persistence / migration defaults. Use $table->string('status')->default(UserStatus::ACTIVE) (or ->default(UserStatus::ACTIVE->value) if the cast object isn't scalar-safe in your migration context). Keep enums as strings in the database; storing integer ordinals makes every future insert/delete reordering a data migration.

Testing. Add a single test that asserts values() equals the DB column's allowed set, and a factory state per enum value (->state(UserStatus::SUSPENDED)) so feature tests read like prose instead of magic strings.

Feature flags / state machines. Enumerations compose well with transition maps:

const TRANSITIONS = [
    self::ACTIVE    => [self::SUSPENDED, self::DELETED],
    self::SUSPENDED => [self::ACTIVE, self::DELETED],
];

Keeping transition tables inside the enum (rather than in a service) makes canTransitionTo() discoverable and unit-testable without the container.

Gotchas and Tips

Verify the package is actually maintained before betting on it. It currently shows no stars and no dependents, which means: no community answers on Stack Overflow, no third-party blog posts to debug against, and a real chance the eloquent/enumeration base it wraps has moved on. Pin the version in composer.json, and read composer.lock — if it drags in a stale eloquent/enumeration, check that constraint against your PHP version. For a package this small, the fallback (bensampo/laravel-enum or a hand-rolled abstract class Enum) is a day of work; do not let it become an unmovable dependency in your domain layer.

Equality is the #1 source of bugs. Depending on the version, an enum attribute may come back as an object, a string, or a lazily-cast value. $user->status === UserStatus::ACTIVE will silently be false when $user->status is an object and UserStatus::ACTIVE is a string constant. Use the package's comparison helper (is(), equals()) if it provides one, and never use === on cast attributes until you've proven what type comes back with dd(get_debug_type($user->status)).

Serialization. $model->toArray() / API resources will emit whatever the cast produces. If it emits {} or the class name instead of "active", add #[Castable]/JsonSerializable handling or cast in the resource — test json_encode($user) explicitly rather than assuming.

Config and cache quirks. If the package publishes a config file, any cached config (php artisan config:cache) will mask edits during local debugging — the classic "my change does nothing" trap. Also re-run composer dump-autoload after generating enums if the generator writes files into a non-PSR-4 path.

Extension points worth using. The base class is the extension point: add labels(), colors(), toSelectArray(), random(), isValid() as traits applied to all your enums (App\Enums\Concerns\HasLabels). Do not fork the vendor class — one composer update erases it.

Do not add behaviour that belongs elsewhere. Enums are a good home for identity and static metadata (labels, transitions, allowed values) and a bad home for behaviour that needs dependencies (sending mail on status change, charging a card). The moment you want to inject a service into an enum, you want a service class.

Debugging checklist when an enum "doesn't work": (1) composer dump-autoload; (2) get_debug_type($value) to confirm object-vs-string; (3) confirm the cast key spelling matches the column; (4) confirm the constant value matches what's actually in the DB (a bad seeder writing 'Active' vs 'active' will fail lookup silently, returning null rather than throwing); (5) check whether the base library throws or returns null for unknown values — configure that deliberately, because it decides whether bad data surfaces as a 500 or a confusing null three layers deep.

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