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?