PHP 8.0+ 支持原生 Attribute,配合 Reflection 可实现元编程;通过 getAttributes() 获取并用 newInstance() 实例化自定义注解类,支持类、方法、参数等多目标标记,适用于路由、权限、日志等行为增强。

PHP 8.0+ 支持原生 Attribute(即注解),配合反射(Reflection)可实现轻量级元编程。要获取类、方法或属性上的自定义 attribute 并解析执行逻辑,核心是使用 ReflectionClass、ReflectionMethod 等的 getAttributes() 方法。
定义自定义 Attribute 类
Attribute 必须用 #[Attribute] 标记,并指定作用域(如 Attribute::TARGET_CLASS)。它本身是一个普通类,可带构造参数:
#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)]
class Route
{
public function __construct(
public string $path,
public string $method = 'GET'
) {}
}
用反射读取并匹配 Attribute
通过反射对象调用 getAttributes() 获取所有 attribute 实例,再用 isInstance() 或直接类型检查筛选目标 attribute:
$ref = new ReflectionClass(UserController::class);
$attrs = $ref->getAttributes(Route::class);
foreach ($attrs as $attr) {
$route = $attr->newInstance(); // 触发构造,拿到实例
echo "Route: {$route->method} {$route->path}\n";
}
-
getAttributes()返回ReflectionAttribute[]数组,不传参则返回全部,传类名则只返回该类型 -
newInstance()安全执行构造逻辑,支持带参、默认值、类型约束 - 若 attribute 构造失败(如类型不匹配),会抛出
Error,建议加 try-catch
在方法或参数上使用 Attribute 做行为增强
Attribute 不仅能标记类,还能标记方法、参数、属性等,适合做权限校验、日志、自动绑定等:
立即学习“PHP免费学习笔记(深入)”;
class Auth
{
public function __construct(public string $role) {}
}
class AdminController
{
#[Auth('admin')]
public function deleteUser(int $id): void
{
// ...
}
}
// 反射检查方法是否需鉴权
$method = new ReflectionMethod(AdminController::class, 'deleteUser');
$authAttr = $method->getAttributes(Auth::class)[0] ?? null;
if ($authAttr) {
$auth = $authAttr->newInstance();
if (!hasRole($auth->role)) {
throw new PermissionDeniedException();
}
}
结合注解与运行时逻辑实现简易路由分发
可基于 class 和 method 的 #[Route] 自动生成路由映射表:
- 扫描控制器目录,用
get_declared_classes()或 Composer autoload + 文件遍历获取候选类 - 对每个类,检查
getAttributes(Route::class)获取全局路径前缀 - 遍历其 public 方法,检查方法级
#[Route],拼接完整路径 - 注册闭包或控制器动作到路由调度器中
这种模式避免配置文件,代码即契约,适合中小型 CLI 或 API 服务快速搭建。



















