DEV Community

Cover image for Enhancing Enum Constants in Laravel with Description and Label Attributes
Rashid Ali
Rashid Ali

Posted on

Enhancing Enum Constants in Laravel with Description and Label Attributes

PHP attributes provide a powerful way to add metadata to classes and constants, enhancing readability and organization in frameworks like Laravel. Let's explore how to use Description and Label attributes to annotate enum constants in Laravel, specifically with an OrderStatus example.

Understanding PHP Attributes in Enums

PHP attributes allow us to attach metadata to classes, methods, properties, and constants. In Laravel, this feature can streamline the management of descriptive metadata for enum constants such as status codes or types.

Implementing Description and Label Attributes

Step 1: Define Attribute Classes

Create attribute classes that extend a base AttributeProperty class to encapsulate metadata values:

<?php

namespace App\Attributes;

use Attribute;

/* Base class for attribute properties */
#[Attribute(Attribute::TARGET_CLASS_CONSTANT)]
class AttributeProperty
{
    public const ATTRIBUTE_PATH = 'App\Attributes\\';

    public function __construct(
        protected mixed $value,
    ) {
    }

    public function get(): mixed
    {
        return $this->value;
    }
}

/* Attribute for describing enum constants */
#[Attribute(Attribute::TARGET_CLASS_CONSTANT)]
class Description extends AttributeProperty
{
}

/* Attribute for labeling enum constants */
#[Attribute(Attribute::TARGET_CLASS_CONSTANT)]
class Label extends AttributeProperty
{
}

<?php

namespace App\Traits;

use App\Attributes\AttributeProperty;
use BadMethodCallException;
use Illuminate\Support\Str;
use ReflectionAttribute;
use ReflectionEnum;

trait AttributableEnum
{
    /**
     * Call the given method on the enum case
     *
     */
    public function __call(string $method, array $arguments): mixed
    {
        // Get attributes of the enum case with reflection API
        $reflection = new ReflectionEnum(static::class);
        $attributes = $reflection->getCase($this->name)->getAttributes();

        // Check if attribute exists in our attributes list
        $filtered_attributes = array_filter($attributes, fn (ReflectionAttribute $attribute) => $attribute->getName() === AttributeProperty::ATTRIBUTE_PATH . Str::ucfirst($method));

        // If not, throw an exception
        if (empty($filtered_attributes)) {
            throw new BadMethodCallException(sprintf('Call to undefined method %s::%s()', static::class, $method));
        }

        return array_shift($filtered_attributes)->newInstance()->get();
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Create the Enum Using Attributes

Define an enum OrderStatus that uses Label and Description attributes to annotate its constants:

<?php

namespace App\Enums;

use App\Attributes\Label;
use App\Attributes\Description;
use App\Attributes\AttributeProperty;
use App\Traits\AttributableEnum;

enum OrderStatus: string
{
    use AttributableEnum;

    #[Label('Pending')]
    #[Description('Order is pending')]
    case Pending = 'pending';

    #[Label('Confirmed')]
    #[Description('Order is confirmed')]
    case Confirmed = 'confirmed';

    #[Label('Canceled')]
    #[Description('Order has been canceled')]
    case Canceled = 'canceled';

    #[Label('Completed')]
    #[Description('Order has been completed')]
    case Completed = 'completed';
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Accessing Enum Attributes

With the defined Description and Label attributes, you can access their values through methods defined in AttributeProperty or directly within your Laravel application's logic. For example, to retrieve the description of an enum constant:

<?php

$statusDescription = OrderStatus::Pending()->getDescription();
// Output: 'Order is pending'
Enter fullscreen mode Exit fullscreen mode

Conclusion

Using PHP attributes such as Label and Description with enums in Laravel enables you to centralize and manage descriptive metadata for enum constants effectively. This approach improves code clarity, simplifies maintenance, and enhances the readability of your Laravel applications.

By leveraging attributes in enums, you can streamline how you define and use status codes, types, or any other constant values that require additional descriptive information.

Start using PHP attributes in enums today to enhance your Laravel projects and maintain a clean, organized codebase!

Top comments (4)

Collapse
 
altesack profile image
Marat Latypov

Smart! Does autocomplete work in IDE? For example when you start type getDescription?

Collapse
 
realrashid profile image
Rashid Ali

Absolutely! IDE autocomplete works seamlessly with PHP attributes.
When you start typing getDescription() after accessing an enum constant like OrderStatus::Pending(), the IDE recognizes the method because it's dynamically accessed through PHP's reflection API.

Collapse
 
prwnr profile image
Rafał

I don't think it will see that method in this case.

You could however add type hint to class doc to get to see it.

Collapse
 
realrashid profile image
Rashid Ali

Since getDescription() is accessed dynamically through reflection, IDE autocomplete might not directly recognize it.
However, the use of attributes in enums is optimized for descriptive metadata like descriptions and labels, maintaining a clean and organized codebase in Laravel.