JieAnthony / laravel-enum

Enum helper for laravel based on the enum feature of php 8.1.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

laravel enum helper base php version 8.1

Latest Version on Packagist GitHub Tests Action Status GitHub Code Style Action Status Coverage Status Scrutinizer Code Quality Total Downloads

Enum helper for laravel10 based on the enum feature of php 8.1.

Installation

You can install the package via composer:

composer require biiiiiigmonster/laravel-enum

Usage

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;
}

Invokable

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

Use static calls to get the primitive value

TaskStatus::INCOMPLETE(); // 0
TaskStatus::COMPLETED(); // 1
TaskStatus::CANCELED(); // 2
Role::ADMINISTRATOR(); // 'ADMINISTRATOR'
Role::SUBSCRIBER(); // 'SUBSCRIBER'
Role::GUEST(); // 'GUEST'

Invoke instances to get the primitive value

public function updateStatus(TaskStatus $status, Role $role)
{
    $this->record->setStatus($status(), $role());
}

Enhancement

Helper provide many static methods for you to enhance experience with enums.

Names

This helper returns a list of case names in the enum.

TaskStatus::names(); // ['INCOMPLETE', 'COMPLETED', 'CANCELED']
Role::names(); // ['ADMINISTRATOR', 'SUBSCRIBER', 'GUEST']

Values

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']

Options

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'
    ]
*/

Tables

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']
    ]
*/

From

This helper adds from() and tryFrom() to pure enums, and adds fromName() and tryFromName() to all enums.

Important Notes:

  • BackedEnum instances already implement their own from() and tryFrom() methods, which will not be overridden by this trait. Attempting to override those methods in a BackedEnum causes a fatal error.
  • Pure enums only have named cases and not values, so the from() and tryFrom() methods are functionally equivalent to fromName() and tryFromName()
Use the from() method
Role::from('ADMINISTRATOR'); // Role::ADMINISTRATOR
Role::from('NOBODY'); // Error: ValueError
Use the tryFrom() method
Role::tryFrom('GUEST'); // Role::GUEST
Role::tryFrom('NEVER'); // null
Use the fromName() method
TaskStatus::fromName('INCOMPLETE'); // TaskStatus::INCOMPLETE
TaskStatus::fromName('MISSING'); // Error: ValueError
Role::fromName('SUBSCRIBER'); // Role::SUBSCRIBER
Role::fromName('HACKER'); // Error: ValueError
Use the tryFromName() method
TaskStatus::tryFromName('COMPLETED'); // TaskStatus::COMPLETED
TaskStatus::tryFromName('NOTHING'); // null
Role::tryFromName('GUEST'); // Role::GUEST
Role::tryFromName('TESTER'); // null

Random

This helper returns an instance of case by random.

TaskStatus::random(); // TaskStatus::COMPLETED
Role::random(); // Role::GUEST

Meta

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;
}

Creating meta attributes

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'

Access the metadata

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'
    ]
]

Use the fromMeta() method

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

Use the tryFromMeta() method

TaskStatus::tryFromMeta($green); // TaskStatus::COMPLETED
TaskStatus::tryFromMeta($blue); // null

Validation

Usually, we need limit your application's incoming data to a specified enums, laravel provides the basic rule, but here we have perfected it.

Array Validation

You can use the 'array' syntax for rules.

Enum

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)],
    ]);
}

EnumMeta

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)],

Pipe Validation

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,

Validation messages

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"

Localization

Labels

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']

Artisan Command

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;
    // ...
}

Testing

composer test

Changelog

Please see CHANGELOG for more information on what has changed recently.

References

License

The MIT License (MIT). Please see License File for more information.

About

Enum helper for laravel based on the enum feature of php 8.1.

License:MIT License


Languages

Language:PHP 100.0%