Metadata
Add custom properties and behaviors to enum cases using attributes.
Overview
Section titled “Overview”The Metadata trait allows you to:
- Attach custom properties to enum cases
- Access properties via dynamic methods
- Find cases by metadata values
- Transform property values automatically
Basic Setup
Section titled “Basic Setup”use Cline\Enums\Concerns\Metadata;use Cline\Enums\Meta\Meta;use Cline\Enums\Meta\MetaProperty;
// Define your meta properties#[Attribute]class Description extends MetaProperty {}
#[Attribute]class Color extends MetaProperty {}
// Apply to your enum#[Meta(Description::class, Color::class)]enum TaskStatus: int{ use Metadata;
#[Description('Incomplete Task')] #[Color('red')] case Incomplete = 0;
#[Description('Completed Task')] #[Color('green')] case Completed = 1;
#[Description('Canceled Task')] #[Color('gray')] case Canceled = 2;}Accessing Metadata
Section titled “Accessing Metadata”TaskStatus::Incomplete->description(); // 'Incomplete Task'TaskStatus::Completed->color(); // 'green'Creating Meta Properties
Section titled “Creating Meta Properties”Each meta property is a class extending MetaProperty:
#[Attribute]class Color extends MetaProperty {}
#[Attribute]class Description extends MetaProperty {}
#[Attribute]class Icon extends MetaProperty {}Advanced Features
Section titled “Advanced Features”Custom Method Names
Section titled “Custom Method Names”Override the default method name:
#[Attribute]class Description extends MetaProperty{ public static function method(): string { return 'note'; // Use ->note() instead of ->description() }}Value Transformation
Section titled “Value Transformation”Transform values before they’re returned:
#[Attribute]class Color extends MetaProperty{ protected function transform(mixed $value): mixed { return "text-{$value}-500"; // 'green' becomes 'text-green-500' }}Default Values
Section titled “Default Values”Provide defaults for cases without the attribute:
#[Attribute]class Priority extends MetaProperty{ public function defaultValue(): mixed { return 'normal'; // Cases without Priority attribute return 'normal' }}Finding Cases by Metadata
Section titled “Finding Cases by Metadata”fromMeta()
Section titled “fromMeta()”Find a case by its metadata value (throws ValueError if not found):
TaskStatus::fromMeta(Color::make('green')); // TaskStatus::COMPLETEDTaskStatus::fromMeta(Color::make('blue')); // Error: ValueErrortryFromMeta()
Section titled “tryFromMeta()”Find a case by its metadata value (returns null if not found):
TaskStatus::tryFromMeta(Color::make('green')); // TaskStatus::COMPLETEDTaskStatus::tryFromMeta(Color::make('blue')); // nullReal-World Examples
Section titled “Real-World Examples”UI Configuration
Section titled “UI Configuration”#[Attribute]class Color extends MetaProperty {}
#[Attribute]class Icon extends MetaProperty {}
#[Attribute]class Label extends MetaProperty {}
#[Meta(Color::class, Icon::class, Label::class)]enum OrderStatus: string{ use Metadata;
#[Color('yellow')] #[Icon('clock')] #[Label('Pending')] case Pending = 'pending';
#[Color('blue')] #[Icon('truck')] #[Label('Shipped')] case Shipped = 'shipped';
#[Color('green')] #[Icon('check')] #[Label('Delivered')] case Delivered = 'delivered';}
// In your view<span class="text-<?= $order->status->color() ?>-500"> <i class="icon-<?= $order->status->icon() ?>"></i> <?= $order->status->label() ?></span>Permissions & Roles
Section titled “Permissions & Roles”#[Attribute]class Permissions extends MetaProperty{ protected function transform(mixed $value): array { return is_string($value) ? explode(',', $value) : $value; }}
#[Meta(Permissions::class)]enum Role: string{ use Metadata;
#[Permissions('read')] case GUEST = 'guest';
#[Permissions('read,write')] case USER = 'user';
#[Permissions('read,write,delete,admin')] case ADMIN = 'admin';}
if (in_array('write', $user->role->permissions())) { // User can write}State Machine Transitions
Section titled “State Machine Transitions”#[Attribute]class AllowedTransitions extends MetaProperty {}
#[Meta(AllowedTransitions::class)]enum OrderStatus: string{ use Metadata;
#[AllowedTransitions(['shipped', 'canceled'])] case Pending = 'pending';
#[AllowedTransitions(['delivered', 'returned'])] case Shipped = 'shipped';
#[AllowedTransitions(['returned'])] case Delivered = 'delivered';}
$canTransitionTo = in_array( $newStatus->value, $currentStatus->allowedTransitions());IDE Support
Section titled “IDE Support”Add @method annotations for better IDE support:
/** * @method string description() * @method string color() * @method string icon() */#[Meta(Description::class, Color::class, Icon::class)]enum TaskStatus: int{ use Metadata; // ...}Or create a trait for reusable metadata:
/** * @method string color() * @method string icon() */trait HasUIMetadata{ use Metadata;}
#[Meta(Color::class, Icon::class)]enum TaskStatus: int{ use HasUIMetadata; // ...}