PHP 注解路由实现原理
PHP8 新特性支持注解(Attribute),其实和 Java 的注解很类似,因为是新特性刚出不久,生态还需要完善。这里我简单说一下实现原理,代码仅作为参考并非完整的实现过程,但是核心逻辑已经阐明清楚。
大致实现过程为:了解 Laravel 的路由注册过程,通过反射获取定义过注解路由的方法,接着将注解路由的参数和这个方法统一注册到 Laravel 的路由中,这样在整个应用声明周期内即可完成注解路由自动注册。
这里以注解路由为例,解释一下为何以下代码段会自动注册路由到 /api/test
路由。
控制器类:
1 |
|
注解类:
1 |
|
在这之前我们需要了解 Laravel 的路由是在 routes 目录下统一管理,例如 api.php
和 web.php
,实际上 Laravel 在其声明周期执行过程中会通过服务提供者自动注册在 routes
文件夹下的路由文件内的具体路由到应用中。因此我们也需要做这一步,但是我们的路由不再写在 routes
目录下,而是写到 app/Http/Controllers
文件夹下的每个控制器对应的方法注解中。
首先,我们需要扫描整个 app/Http/Controllers
目录下的全部 .php
文件,由于 PSR 规范的存在,控制器的类名和其文件名是相同的,比如 app/Http/Controllers/TestController.php
的类名就是 TestController
,所以我们可以通过字符串替换的方式得到 TestController::class
,也就是类本身。
接着,我们通过反射方法 (new TestController())->getMethods();
获取 TestController::class
下的全部方法,再通过 $attributes = $method->getAttributes('Get');
以及判断是否存在 Get[]
注解来知道这个方法是否有做注解路由,找到我们需要的那些已经被定义过注解路由的方法。
然后,我们通过反射方法获取注解中传入的参数 $uri
和 $name
:
1 |
|
最后,我们把以上这些逻辑引入到 app/Providers/AppServiceProvider.php
的 boot()
方法中即可,完成注解路由注册。