phpreflectionphp-8php-attributes

How to get method name from PHP 8 attribute (reflection)


I'm working on small PHP framework (for learning). It has a file with LoginController class containing a method with Route attribute (code below). Is there any way to get the name of the method in the Route attribute class using Reflection?

Class with method using attribute:

class LoginController {
    #[Route('GET', '/login')]
    public function index() {
        // some code
    }
}

"Route" attribute class:

use Attribute;
use ReflectionMethod;

#[Attribute]
class Route {
    public function __construct($method, $routeUri) {
        // Can I get the method name ("index") from attribute instead of writing it?
        // And the class name?
        $reflection = new ReflectionMethod(\App\Controllers\LoginController::class, 'index');
        $closure = $reflection->getClosure();

        // Register a route...
        Router::add($method, $routeUri, $closure);
    }
}

Solution

  • Reflection is an option, but please be aware that you will be looping over all the attributes of all the methods in a class (at least until a matching one is found). Of course, if all routes need to be registered, this isn't that bad.

    $classRef = new ReflectionClass(LoginController::class);
    foreach ($classRef->getMethods() as $method) {
        $methodRef = new ReflectionMethod($method->class, $method->name);
        foreach ($methodRef->getAttributes() as $attribute) {
            if (
                $attribute->getName() === 'Route' 
                && $attribute->getArguments() === [$method, $routeUri]
            ) {
                // you can register your route here
            }
        }
    }
    

    As far as classes go, the easiest way to go is just make an array with all your controller class names. There are packages out there that can detect all classes in a given namespace, which could be used for autodetecting your controllers.