Enum helper for laravel10 based on the enum feature of php 8.1.
You can install the package via composer:
composer require biiiiiigmonster/laravel-enum
Apply the trait on your enum
use BiiiiiigMonster\LaravelEnum\Concerns\EnumTraits;
// backed enum.
enum TaskStatus: int
{
use EnumTraits;
case INCOMPLETE = 0;
case COMPLETED = 1;
case CANCELED = 2;
}
// pure enum.
enum Role
{
use EnumTraits;
case ADMINISTRATOR;
case SUBSCRIBER;
case GUEST;
}
This helper lets you get the primitive value of a backed enum, or the name of a pure enum, by "invoking" it — either statically (MyEnum::FOO()
instead of MyEnum::FOO
), or as an instance ($enum()
).
That way, you can use enums as array keys:
'statuses' => [
TaskStatus::INCOMPLETE() => ['some configuration'],
TaskStatus::COMPLETED() => ['other configuration'],
],
Or access the underlying primitives for any other use cases:
public function updateStatus(int $status): void;
$task->updateStatus(TaskStatus::COMPLETED());
The main point: this is all without having to append ->value
to everything:
TaskStatus::CANCELED; // => TaskStatus instance
TaskStatus::CANCELED(); // => 2
TaskStatus::INCOMPLETE(); // 0
TaskStatus::COMPLETED(); // 1
TaskStatus::CANCELED(); // 2
Role::ADMINISTRATOR(); // 'ADMINISTRATOR'
Role::SUBSCRIBER(); // 'SUBSCRIBER'
Role::GUEST(); // 'GUEST'
public function updateStatus(TaskStatus $status, Role $role)
{
$this->record->setStatus($status(), $role());
}
Helper provide many static methods for you to enhance experience with enums.
This helper returns a list of case names in the enum.
TaskStatus::names(); // ['INCOMPLETE', 'COMPLETED', 'CANCELED']
Role::names(); // ['ADMINISTRATOR', 'SUBSCRIBER', 'GUEST']
This helper returns a list of case values for backed enums, or a list of case names for pure enums (making this functionally equivalent to ::names()
for pure Enums)
TaskStatus::values(); // [0, 1, 2]
Role::values(); // ['ADMINISTRATOR', 'SUBSCRIBER', 'GUEST']
This helper returns an array, that key is each instance invoke ()
return, and value is instance ->label()
returns.
TaskStatus::options();
/*
[
0 => 'Incomplete',
1 => 'Completed',
2 => 'Canceled'
]
*/
Role::options();
/*
[
'ADMINISTRATOR' => 'Administrator',
'SUBSCRIBER' => 'Subscriber',
'GUEST' => 'Guest'
]
*/
This helper returns a list of case map array that each instance, if instance append attributes that extended Meta
, the map array including more.
TaskStatus::tables();
/*
[
['name' => 'INCOMPLETE', 'value' => 0],
['name' => 'COMPLETED', 'value' => 1],
['name' => 'CANCELED', 'value' => 2]
]
*/
Role::tables();
/*
[
['name' => 'ADMINISTRATOR'],
['name' => 'SUBSCRIBER'],
['name' => 'GUEST']
]
*/
This helper adds from()
and tryFrom()
to pure enums, and adds fromName()
and tryFromName()
to all enums.
Important Notes:
BackedEnum
instances already implement their ownfrom()
andtryFrom()
methods, which will not be overridden by this trait. Attempting to override those methods in aBackedEnum
causes a fatal error.- Pure enums only have named cases and not values, so the
from()
andtryFrom()
methods are functionally equivalent tofromName()
andtryFromName()
Role::from('ADMINISTRATOR'); // Role::ADMINISTRATOR
Role::from('NOBODY'); // Error: ValueError
Role::tryFrom('GUEST'); // Role::GUEST
Role::tryFrom('NEVER'); // null
TaskStatus::fromName('INCOMPLETE'); // TaskStatus::INCOMPLETE
TaskStatus::fromName('MISSING'); // Error: ValueError
Role::fromName('SUBSCRIBER'); // Role::SUBSCRIBER
Role::fromName('HACKER'); // Error: ValueError
TaskStatus::tryFromName('COMPLETED'); // TaskStatus::COMPLETED
TaskStatus::tryFromName('NOTHING'); // null
Role::tryFromName('GUEST'); // Role::GUEST
Role::tryFromName('TESTER'); // null
This helper returns an instance of case by random.
TaskStatus::random(); // TaskStatus::COMPLETED
Role::random(); // Role::GUEST
This feature lets you add meta data to enum cases, it's used by way of attributes.
use BiiiiiigMonster\LaravelEnum\Concerns\EnumTraits;
use App\Enums\Metas\{Description, Color};
enum TaskStatus: int
{
use EnumTraits;
#[Description('Incomplete Task')] #[Color('red')]
case INCOMPLETE = 0;
#[Description('Completed Task')] #[Color('green')]
case COMPLETED = 1;
#[Description('Canceled Task')] #[Color('gray')]
case CANCELED = 2;
}
Each meta attribute needs to exist as an Attribute.
use BiiiiiigMonster\LaravelEnum\Concerns\Meta;
use Attribute;
#[Attribute]
class Color extends Meta {}
#[Attribute]
class Description extends Meta {}
Inside the attribute, you can customize a few things. For instance, you may want to use a different method name than the one derived from the class name (Description
becomes description()
by default). To do that, define the alias
static property on the meta:
#[Attribute]
class Description extends Meta
{
public static string $alias = 'note';
}
With the code above, the ->description()
of a case will be accessible as ->note()
.
Another thing you can customize is the passed value. For instance, to wrap a color name like text-{$color}-500
, you'd add the following transform()
method:
#[Attribute]
class Color extends Meta
{
protected function transform(mixed $value): string
{
return "text-{$value}-500";
}
}
And now the returned color will be correctly transformed:
TaskStatus::COMPLETED->color(); // 'text-green-500'
By accessing the attribute method name, you can get the meta value:
TaskStatus::INCOMPLETE->description(); // 'Incomplete Task'
TaskStatus::COMPLETED->color(); // 'green'
Also, ::tables()
static method can return all meta attribute maps on each instance.
$tables = TaskStatus::tables();
// $tables
[
[
'name' => 'INCOMPLETE',
'value' => 0,
'description' => 'Incomplete Task',
'color' => 'red'
],
[
'name' => 'COMPLETED',
'value' => 1,
'description' => 'Completed Task',
'color' => 'green'
],
[
'name' => 'CANCELED',
'value' => 2,
'description' => 'Canceled Task',
'color' => 'gray'
]
]
Similarly, you can also get the enum case instance through the meta instance.
$green = Color::make('green');// new Color('green');
$blue = Color::make('blue');// new Color('blue');
TaskStatus::fromMeta($green); // TaskStatus::COMPLETED
TaskStatus::fromMeta($blue); // Error: ValueError
TaskStatus::tryFromMeta($green); // TaskStatus::COMPLETED
TaskStatus::tryFromMeta($blue); // null
Usually, we need limit your application's incoming data to a specified enums, laravel provides the basic rule, but here we have perfected it.
You can use the 'array' syntax for rules.
Validate that a parameter is an instance of a given enum, it's similar to Enum Rules
and can support pure enums.
use BiiiiiigMonster\LaravelEnum\Rules\Enum;
public function store(Request $request)
{
$this->validate($request, [
'status' => ['required', new Enum(TaskStatus::class)],
'role' => ['required', new Enum(Role::class)],
]);
}
Additionally, validate that a parameter is an instance of the given meta in the given enum.
use BiiiiiigMonster\LaravelEnum\Rules\EnumMeta;
public function store(Request $request)
{
$this->validate($request, [
'color' => ['required', new EnumMeta(TaskStatus::class, Color::class)],
]);
}
EnumMeta
rule takes two parameters, the first is given enum, the second is given meta, if parameter name is same of meta method name, you can omit it:
'color' => ['required', new EnumMeta(TaskStatus::class)],
You can also use the 'pipe' syntax for rules.
- enumerate: enum_class
- enum_meta: enum_class,[meta_attribute]
'status' => 'required|enumerate:' . TaskStatus::class,
'color' => 'required|enum_meta:' . TaskStatus::class . ',' . Color::class,
If needed, you can modify the error message when validated fails.
Run the following command to publish the language files to your lang
folder:
php artisan vendor:publish --provider="BiiiiiigMonster\LaravelEnum\EnumServiceProvider" --tag="translations"
The enum instances are descriptive, and we have added translation capabilities for this.
You can translate the strings returned by the enum instance's ->label()
method using Laravel's built-in localization features.
Add a new enums.php
keys file for each of your supported languages. In this example there is one for English and one for Spanish:
// lang/en/enums.php
<?php declare(strict_types=1);
use App\Enums\TaskStatus;
return [
TaskStatus::class => [
TaskStatus::INCOMPLETE() => 'Incomplete',
TaskStatus::COMPLETED() => 'Completed',
TaskStatus::CANCELED() => 'Canceled',
],
];
// lang/es/enums.php
<?php declare(strict_types=1);
use App\Enums\TaskStatus;
return [
TaskStatus::class => [
TaskStatus::INCOMPLETE() => 'Incompleto',
TaskStatus::COMPLETED() => 'Completo',
TaskStatus::CANCELED() => 'Cancelación',
],
];
Now, you just need to make sure that your enum implements the Localizable
interface as demonstrated below:
use BiiiiiigMonster\LaravelEnum\Concerns\EnumTraits;
use BiiiiiigMonster\LaravelEnum\Contracts\Localizable;
enum TaskStatus: int implements Localizable
{
use EnumTraits;
// ...
}
The ->label()
method will now look for the value in your localization files:
// en/enums.php
TaskStatus::CANCELED->label();// 'Canceled'
// es/enums.php
TaskStatus::CANCELED->label();// 'Cancelación'
and the ::options()
static method returned array's value also be localized:
// en/enums.php
TaskStatus::options();// [0 => 'Incomplete', 1 => 'Completed', 2 => 'Canceled']
// es/enums.php
TaskStatus::options();// [0 => 'Incompleto', 1 => 'Completo', 2 => 'Cancelación']
If you want your IDE to autocomplete the static instantiation helpers, you can generate PHPDoc annotations through an artisan command.
By default, all Enums in app/Enums
will be annotated (you can change the folder by passing a path to --folder
)
php artisan enum:phpdoc
Also, you can annotate a single class by specifying the class name
php artisan enum:phpdoc "App\Enums\TaskStatus"
use BiiiiiigMonster\LaravelEnum\Concerns\EnumTraits;
use App\Enums\Metas\{Description, Color};
/**
* @method static int INCOMPLETE()
* @method static int COMPLETED()
* @method static int CANCELED()
* @method mixed description()
* @method mixed color()
*/
enum TaskStatus: int
{
use EnumTraits;
// ...
}
composer test
Please see CHANGELOG for more information on what has changed recently.
The MIT License (MIT). Please see License File for more information.