Search code examples
phpattributesphp-8

How to read class methods attributes in php 8?


Lets say I have the following attribute declaration

#[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)]
class Route
{   
    public function __construct(
        public string $path,
        public ?string $method = null,
        public ?string $alias = null
    )
    {}
}

and I use it in some controller methods like so:

class Controller
{
    #[Route('/index/')]
    #[Route('/home/', alias: 'home')]
    public function index()
    {
        ...
    }
    
    #[Route('/create/', 'POST')]
    public function create(Request $request)
    {
        //...
    }
}

How could I obtain those attribute instances and read it's properties?


Solution

  • You can do it by using native php reflection api.

    First, you will have to retrieve the desired methods reflection. In the example bellow, I will retrieve all public methods:

    $reflectionClass = new ReflectionClass(Controller::class);
    $methods = $reflectionClass->getMethods(ReflectionMethod::IS_PUBLIC);
    

    This will return an array containing all public methods reflection.

    Then, to read it and retrieve those Route instances, simply loop through it and use "newInstance()" attribute reflection method. Like so:

    foreach ($methods as $method) {     
        $attributes = $method->getAttributes(Route::class);
    
        echo "reflecting method '", $method->getName(), "'\r\n";
        foreach ($attributes as $attribute) {
           var_dump($attribute->newInstance());
        }
    }
    

    This will output:

    reflecting method 'index'
    object(Route)#8 (3) {
      ["path"]=>
      string(7) "/index/"
      ["method"]=>
      NULL
      ["alias"]=>
      NULL
    }
    object(Route)#8 (3) {
      ["path"]=>
      string(6) "/home/"
      ["method"]=>
      NULL
      ["alias"]=>
      string(4) "home"
    }
    
    reflecting method 'create'
    object(Route)#7 (3) {
      ["path"]=>
      string(8) "/create/"
      ["method"]=>
      string(4) "POST"
      ["alias"]=>
      NULL
    }
    

    Here is the gist with the full working example: https://gist.github.com/carloscarucce/fce40cb3299dd69957db001c21422b04