vixen / laravel-enums
A Laravel package that enhances PHP enums.
Requires
- php: ^8.3
- illuminate/support: ^11.0|^12.0|^13.0
Requires (Dev)
- orchestra/testbench: ^10.11
- pestphp/pest: ^3.2
- pestphp/pest-plugin-laravel: ^3.0
README
A collection of composable traits and attributes for working with PHP backed enums in Laravel.
Requirements
- PHP 8.3+
- Laravel 11, 12, or 13
Installation
composer require vixen/laravel-enums
Usage
Add any combination of traits to your backed enum:
use Vixen\Enums\Attributes\Description; use Vixen\Enums\Attributes\Label; use Vixen\Enums\Attributes\LongLabel; use Vixen\Enums\Attributes\ShortLabel; use Vixen\Enums\HasDescriptions; use Vixen\Enums\HasLabels; use Vixen\Enums\HasOptions; use Vixen\Enums\HasValues; use Vixen\Enums\Filterable; use Vixen\Enums\Snakeable; use Vixen\Enums\ToArray; use Vixen\Enums\ToValue; enum Status: string { use HasDescriptions; use HasLabels; use HasOptions; use HasValues; use Filterable; use Snakeable; use ToArray; use ToValue; #[Label('Pending')] #[LongLabel('Pending Review')] #[ShortLabel('PND')] #[Description('Items waiting to be reviewed by an administrator')] case Pending = 'pending'; #[Label('Approved')] #[LongLabel('Approved Review')] #[ShortLabel('APR')] #[Description('Items that have passed review')] case Approved = 'approved'; #[Label('Rejected'), LongLabel('Rejected Review'), ShortLabel('REJ')] case Rejected = 'rejected'; }
Traits
HasLabels
Provides label functionality using #[Label], #[LongLabel], and #[ShortLabel] attributes.
// Static methods — return a Collection keyed by enum value Status::labels(); // ['pending' => 'Pending', 'approved' => 'Approved', ...] Status::longLabels(); // ['pending' => 'Pending Review', ...] Status::shortLabels(); // ['pending' => 'PND', ...] // Instance methods — return the label for a single case Status::Pending->label(); // 'Pending' Status::Pending->longLabel(); // 'Pending Review' Status::Pending->shortLabel(); // 'PND'
When no attribute is provided, a label is auto-generated from the case name:
case Pending = 'pending'; // Pending->label() returns 'Pending'
Label type parameter
Instead of separate attributes, you can use the type parameter on #[Label]:
#[Label('Pending')] // default label #[Label('Pending Review', type: 'long')] // equivalent to #[LongLabel(...)] #[Label('PND', type: 'short')] // equivalent to #[ShortLabel(...)]
Fallback chain
When requesting a specific label type (e.g., longLabel()), the resolution order is:
- The exact attribute (
#[LongLabel]or#[Label(..., type: 'long')]) - The default
#[Label] - Auto-generated label from the case name
Translation support
#[Label] and #[LongLabel] values are passed through Laravel's __() helper, so you can use translation keys:
#[Label('enums.status.pending')] case Pending = 'pending';
#[ShortLabel] returns the raw string without translation, since it's intended for abbreviations.
HasDescriptions
Provides description functionality using the #[Description] attribute. Useful for longer descriptive text alongside labels.
// Static method — returns a Collection keyed by enum value Status::descriptions(); // ['pending' => 'Items waiting to be reviewed by an administrator', 'approved' => 'Items that have passed review', 'rejected' => null] // Instance method — returns the description for a single case, or null Status::Pending->description(); // 'Items waiting to be reviewed by an administrator' Status::Rejected->description(); // null
Returns null when no #[Description] attribute is present on a case.
Translation support
#[Description] values are passed through Laravel's __() helper, so you can use translation keys:
#[Description('enums.status.pending_description')] case Pending = 'pending';
HasOptions
Returns label-value pairs as a Collection, useful for select dropdowns and form components. Requires the enum to provide a label() method (typically via HasLabels) and a description() method (typically via HasDescriptions).
Status::options(); // [ // ['label' => 'Pending', 'value' => 'pending'], // ['label' => 'Approved', 'value' => 'approved'], // ['label' => 'Rejected', 'value' => 'rejected'], // ] Status::descriptiveOptions(); // [ // ['label' => 'Pending', 'value' => 'pending', 'description' => 'Items waiting to be reviewed by an administrator'], // ['label' => 'Approved', 'value' => 'approved', 'description' => 'Items that have passed review'], // ['label' => 'Rejected', 'value' => 'rejected', 'description' => null], // ]
Customizing fields with only
Both options() and descriptiveOptions() accept an optional only parameter to customize which fields appear in the returned arrays. The value field is always included.
Status::options(only: ['shortLabel', 'description']); // [ // ['value' => 'pending', 'shortLabel' => 'PND', 'description' => 'Items waiting to be reviewed by an administrator'], // ['value' => 'approved', 'shortLabel' => 'APR', 'description' => 'Items that have passed review'], // ['value' => 'rejected', 'shortLabel' => 'REJ', 'description' => null], // ] // Use ['*'] to include all available fields Status::options(only: ['*']); // [ // ['value' => 'pending', 'name' => 'Pending', 'label' => 'Pending', 'shortLabel' => 'PND', 'longLabel' => 'Pending Review', 'description' => '...'], // ... // ]
Available fields: value, name, label, shortLabel, longLabel, description. An InvalidArgumentException is thrown for fields that don't exist on the enum.
HasValues
Returns a Collection of all backed values.
Status::values(); // ['pending', 'approved', 'rejected']
Filterable
Select or exclude specific cases by name. Returns an EnumCollection (see below), so you can chain toOptions() or toDescriptiveOptions() directly.
Status::only(['Pending', 'Approved']); // EnumCollection of [Status::Pending, Status::Approved] Status::except(['Rejected']); // EnumCollection of [Status::Pending, Status::Approved] // Chain with EnumCollection methods Status::only(['Pending', 'Approved'])->toOptions(); // [ // ['label' => 'Pending', 'value' => 'pending'], // ['label' => 'Approved', 'value' => 'approved'], // ]
EnumCollection
A custom collection class extending Laravel's Collection, designed to hold enum cases and provide convenient conversion methods.
use Vixen\Enums\EnumCollection; $collection = new EnumCollection(Status::cases()); $collection->toOptions(); // [ // ['label' => 'Pending', 'value' => 'pending'], // ['label' => 'Approved', 'value' => 'approved'], // ['label' => 'Rejected', 'value' => 'rejected'], // ] $collection->toDescriptiveOptions(); // [ // ['label' => 'Pending', 'value' => 'pending', 'description' => 'Items waiting to be reviewed by an administrator'], // ['label' => 'Approved', 'value' => 'approved', 'description' => 'Items that have passed review'], // ['label' => 'Rejected', 'value' => 'rejected', 'description' => null], // ] // Customize fields with the only parameter $collection->toOptions(only: ['shortLabel', 'description']); // [ // ['value' => 'pending', 'shortLabel' => 'PND', 'description' => '...'], // ... // ]
toOptions() requires the enum to use HasLabels. toDescriptiveOptions() additionally requires HasDescriptions. Both methods accept an optional only parameter — see HasOptions for details.
Returned automatically by Filterable::only() and Filterable::except().
Snakeable
Converts the case name to snake_case.
Status::Pending->snake(); // 'pending' Status::PendingReview->snake(); // 'pending_review'
ToArray
Converts a single case to an associative array. Requires the enum to provide a label() method.
Status::Pending->toArray(); // ['label' => 'Pending', 'value' => 'pending']
ToValue
Explicit accessor for the backed value.
Status::Pending->toValue(); // 'pending'
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Please see CONTRIBUTING for details.
Credits
- Alex Torscho
- All Contributors
License
The MIT License (MIT). Please see License File for more information.