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();
}
}
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';
}
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'
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)
Smart! Does autocomplete work in IDE? For example when you start type
getDescription
?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.
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.
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.