PHP 8 属性是可运行时读取的结构化元数据,须用 ReflectionProperty 获取;注解需标注在属性前且目标类用 #[Attribute(Attribute::TARGET_PROPERTY)] 声明;通过 $prop->getAttributes(Required::class) 获取并 newInstance() 实例化。

PHP 8 的属性(Attributes)不是注释,而是可被运行时读取的结构化元数据。要获取类中属性(property)上标注的注解,必须使用 ReflectionProperty,而不是 ReflectionClass 或 ReflectionMethod —— 因为注解是绑定在具体属性定义上的。
确认属性上已声明注解
注解需直接写在属性声明前,且该注解类必须用 #[Attribute] 声明,并允许作用于属性(Attribute::TARGET_PROPERTY):
#[Attribute(Attribute::TARGET_PROPERTY)]
class Required {
public function __construct(public string $message = 'This field is required') {}
}
class User {
#[Required(message: 'Name cannot be empty')]
public string $name;
#[Required]
public ?int $age = null;
}
用 ReflectionProperty 获取单个属性的注解
先通过 ReflectionClass 找到目标属性,再创建 ReflectionProperty 实例,调用 getAttributes() 提取所有匹配注解:
- 传入注解类名(如
Required::class)可只获取该类型注解 - 不传参数则返回该属性上全部注解实例数组
- 每个
ReflectionAttribute对象支持getName()、getArguments()和newInstance()
示例代码:
修复 Core bailout 状态损坏安全问题,以及 BZ2、DOM、PDO、Opcache/JIT 内存与执行错误,改进 Unicode 字素处理、URL 解析、TLS 流状态、信号分发及会话错误处理。
$rc = new ReflectionClass(User::class);
$rp = $rc->getProperty('name'); // 注意:属性名是字符串,非变量
// 获取所有 Required 注解(返回 ReflectionAttribute[])
$attrs = $rp->getAttributes(Required::class);
if (!empty($attrs)) {
$requiredAttr = $attrs[0]->newInstance(); // 触发构造,得到 Required 实例
echo $requiredAttr->message; // 输出:'Name cannot be empty'
}
批量获取类中所有带注解的属性
遍历类的所有属性,筛选出含指定注解的项:
$rc = new ReflectionClass(User::class);
$propsWithRequired = [];
foreach ($rc->getProperties() as $prop) {
$attrs = $prop->getAttributes(Required::class);
if (!empty($attrs)) {
$propsWithRequired[] = [
'name' => $prop->getName(),
'attr' => $attrs[0]->newInstance()
];
}
}
// 结果:[ ['name' => 'name', 'attr' => Required{...}], ... ]
注意作用域与可见性
ReflectionProperty 默认只能获取 public 属性;若需访问 private 或 protected 属性,需先调用 $prop->setAccessible(true):
- 即使属性是 private,只要它带注解,反射仍可读取其注解信息
-
setAccessible(true)不影响注解读取,仅在后续尝试getValue()时才需要 - 注解本身不依赖属性可见性,
getAttributes()对所有修饰符属性都有效
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










