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 Simple Enum Laravel Package

chadsikorra/php-simple-enum

A lightweight, dependency-free enum implementation for PHP. Define constant sets with helper methods for validation, value lookup, and comparison, useful where native enums aren't available. Simple API that's easy to drop into existing projects.

Deep Wiki
Context7

Getting Started

Install it like any other small utility package:

composer require chadsikorra/php-simple-enum

Before writing anything, do two things:

  1. Open vendor/chadsikorra/php-simple-enum/composer.json and note the PSR-4 namespace. The package is tiny, so the entire API surface is one or two classes — read them end to end (5 minutes) rather than trusting blog snippets.
  2. Confirm the PHP version constraint matches your app. Small utility packages like this often lag behind the newest PHP minor, and if you're on 8.3+ you want to know before CI fails.

There is almost certainly no service provider, no config file, and nothing to publish. Treat it as a library you use in your own classes, not a framework integration.

First use case: kill a magic-number column. The fastest win is any integer column where you've been writing if ($order->status === 2) in five places. Define a class once:

namespace App\Enums;

use ChadSikorra\SimpleEnum\Enum; // verify actual namespace first

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

Then reference OrderStatus::PAID everywhere instead of 1. That alone is worth the dependency. The flag enum variant is the second thing to try — see below.

Implementation Patterns

Validation at the boundary. Every enum class of this style exposes a way to check membership (typically isValid(), isValidValue(), or similar — confirm the exact name). Wrap it in a Laravel validation rule so bad input never reaches your domain:

use Illuminate\Contracts\Validation\Rule;

class EnumRule implements Rule
{
    public function __construct(private string $enumClass) {}

    public function passes($attribute, $value): bool
    {
        return $this->enumClass::isValid($value);
    }

    public function message(): string
    {
        return 'The :attribute is not a valid value.';
    }
}

Register it once and reuse across Form Requests. This is where the package earns its keep in a Laravel app.

Populating selects. Enum classes usually expose the full value set (toArray(), getValues(), getConstants()). Use that to build dropdowns so the UI and the validator can never drift apart:

return view('orders.edit', [
    'statuses' => OrderStatus::toArray(),
]);

If only labels are exposed, map them yourself in a small presenter rather than hardcoding labels in Blade.

Eloquent casts. The package is framework-agnostic, so it won't ship a cast. Write one — it's ten lines and pays off in every model:

class EnumCast implements CastsAttributes
{
    public function __construct(private string $enumClass) {}

    public function get($model, $key, $value, $attributes)
    {
        return $value === null ? null : (int) $value;
    }

    public function set($model, $key, $value, $attributes)
    {
        if (! $this->enumClass::isValid($value)) {
            throw new InvalidArgumentException("Invalid {$key}");
        }
        return $value;
    }
}

Validate in set() — that's the single choke point where a bad value can enter the database.

Flag enums for permissions. The bitmask variant is the more interesting half. Define values as powers of two:

final class Permissions extends FlagEnum
{
    public const READ   = 1;
    public const WRITE  = 2;
    public const DELETE = 4;
    public const ADMIN  = 8;
}

Store the combined integer in one column, then use the package's flag helpers (hasFlag(), addFlag(), removeFlag(), or bitwise &/| if the API is thin) for checks. Keep a labels() map in the class so you can render checkboxes from a single source of truth.

Testing. Because everything is constants, assertions are trivial and readable: $this->assertTrue(Permissions::hasFlag($user->permissions, Permissions::WRITE)). Add a test that asserts every constant is unique and, for flag enums, that each value is a power of two — that catches the one mistake that silently corrupts bitmask data.

Gotchas and Tips

  • Duplicate constant values. PHP allows two constants with the same value; isValid() will still pass but toArray() key-collision behavior is undefined. Add a unit test asserting uniqueness across getConstants().
  • Flag values that aren't powers of two. 3 looks fine but breaks combination logic. Enforce with a test: ($v & ($v - 1)) === 0.
  • Loose comparison. 0 is falsy. If your enum has a 0 case (very common for "pending"), guard against if ($status) idioms — always use isValid() or !== null.
  • String vs int columns. The package stores PHP constants, which can be strings or ints. Decide once per enum and cast consistently in the Eloquent cast, or you'll get "1" !== 1 bugs in queries.
  • No Laravel helpers. Anything you want — Enum::labels(), Enum::toSelectArray(), a validation rule, a cast — you write. Put these in one App\Enums\Concerns trait so every enum gets them for free.
  • Serialization. json_encode($model) will output the raw int/string, not a label. If your API needs labels, add an accessor rather than changing the stored value.
  • Low maintenance risk. At 11 stars with no linked repository, assume the package could go unmaintained. The surface area is small enough that if it ever breaks, you can vendor the two class files into app/Support and drop the Composer requirement in an afternoon — keep your usage funneled through your own base class or trait to make that swap trivial.
  • Extension point. Subclass a project-level BaseEnum extends Enum and have every application enum extend that, not the package class directly. Then any package-level behavior change, or a future migration off the package, touches one file.
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.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route