Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you access attributes on enum cases?

Tags:

php

php-8.1

According to the RFC on Enumerations, attributes can be added to cases by using Attribute::TARGET_CLASS_CONSTANT. (Actually, the RFC says TARGET_CLASS_CONST but that is either a typo or a later change.) I'm having trouble trying to access them using Reflection, however.

Given this setup:

#[Attribute(Attribute::TARGET_CLASS_CONSTANT)]
class TestAttribute
{
    public function __construct(public string $value)
    {
    }
}

enum TestNum
{
    #[TestAttribute('alpha value')]
    case ALPHA;

    #[TestAttribute('beta value')]
    case BETA;
}

I would expect the following code to give me an array with a single attribute, however it returns an empty array.

$obj = TestNum::ALPHA;
$reflection = new ReflectionClass($obj);
$classAttributes = $reflection->getAttributes(TestAttribute::class);
var_dump($classAttributes);

Demo here: https://3v4l.org/uLDVQ#v8.1.2

I found a test-case for this in the PHP src, however the usage isn't what I'd expect. Instead of using an instance, I need to decompose it:

var_dump((new \ReflectionClassConstant(TestNum::class, 'ALPHA'))->getAttributes(TestAttribute::class)[0]->newInstance());

Demo here: https://3v4l.org/BsA9r#v8.1.2

I can use that format, but it feels really hacky since I'm pretty much using reflection inside of reflection:

var_dump((new \ReflectionClassConstant($obj::class, $obj->name))->getAttributes(TestAttribute::class)[0]->newInstance());

Demo here: https://3v4l.org/YY6Oa#v8.1.2

Specifically, the new \ReflectionClassConstant($obj::class, $obj->name) pattern seems strangely boilerplate.

Is there another way to access individual enumeration case attributes that I'm missing?

like image 533
Chris Haas Avatar asked Feb 25 '26 19:02

Chris Haas


1 Answers

#[Attribute( Attribute::TARGET_CLASS_CONSTANT )]
class TestAttribute {
  public function __construct(public string $value) {
  }
}

enum TestNum {
  #[TestAttribute( 'alpha value' )]
  case ALPHA;

  #[TestAttribute( 'beta value' )]
  case BETA;
}

$obj = TestNum::ALPHA;
$ref = new ReflectionEnumUnitCase($obj::class, $obj->name);
$argument = $ref->getAttributes('TestAttribute')[0]->getArguments()[0];

print_r($argument);   // Prints: 'alpha value'
like image 69
lukas.j Avatar answered Mar 01 '26 03:03

lukas.j