Search code examples
phpinheritanceattributesphp-8

How to detect inherited attributes in PHP 8


In the following code, there are 2 attribute classes:

  • Attr that need a string.
  • SubAttr that extends Attr and use a predefined value.
#[Attribute(Attribute::TARGET_METHOD)]
class Attr 
{
    public function __construct(
        public string $value,
    ) 
    { }
}

class SubAttr extends Attr 
{
    public function __construct() { 
        parent::__construct("Predefined value");
    }
}

Testing:

I expected ReflectionMethod::getAttributes() to get Attr data from SubAttr for bar() method.

class Example 
{
    #[Attr("something")]
    public function foo() { }

    #[SubAttr]
    public function bar() { }
}

$method = new ReflectionMethod(Example::class, 'foo');
var_dump(count($method->getAttributes(Attr::class)) == 1); // TRUE

$method = new ReflectionMethod(Example::class, 'bar');
var_dump(count($method->getAttributes(Attr::class)) == 1); // FALSE
// How to get SubAttr attribute?

How getAttributes() can get inherited attributes ?
Is is necessary to get all attributes and check if any of them extends Attr ?


Solution

  • To get inherited attributes, we can use the constant ReflectionAttribute::IS_INSTANCEOF for the parameter $flag of ReflectionClass::getAttributes() method:

    $method->getAttributes(Attr::class, ReflectionAttribute::IS_INSTANCEOF)
    

    Working program:

    #[Attribute(Attribute::TARGET_METHOD)]
    class Attr {
        public function __construct(public string $value) 
        { }
    }
    
    class SubAttr extends Attr {
        public function __construct() { 
            parent::__construct("Predefined value");
        }
    }
    
    class Example 
    {
        #[SubAttr]
        public function bar() { }
    }
    
    $method = new ReflectionMethod(Example::class, 'bar');
    $attrs  = $method->getAttributes(Attr::class, ReflectionAttribute::IS_INSTANCEOF);
    
    var_dump(count($attrs) == 1); // TRUE