


























PHP Attributes ,php8.0之后的特性。
PHP Attributes(注解)是 PHP 8.0 引入的一项重要特性,用于在代码中以结构化、类型安全的方式为类、方法、属性、函数、参数等添加元数据(metadata)。它取代了过去通过注释(如 DocBlock)来传递元数据的“约定式”做法,使元数据成为语言的一等公民。
Attributes(注解) 是一种原生语法,允许开发者将附加信息(元数据)直接附加到程序元素上,例如:
这些元数据可以在运行时通过反射(Reflection)读取和使用。
✅ 关键点:Attributes 不是注释,而是可被解析和使用的实际代码结构。
在 PHP 8 之前,框架(如 Doctrine、Symfony)广泛使用 DocBlock 注解(Annotations) 来实现 ORM 映射、路由定义、验证规则等功能。例如:
/** * @Entity * @Table(name="users") */ class User {}
但这类注解存在以下问题:
PHP Attributes 提供了原生、类型安全、IDE 友好的替代方案。
使用 #[Attribute] 标记一个类为属性类:
<?php use Attribute; #[Attribute] class MyAttribute { public function __construct(public string $value = '') {} }
注意:必须导入
Attribute类(use Attribute;),它是 PHP 内置类。
#[MyAttribute('Hello')] class MyClass { #[MyAttribute('World')] public string $name = ''; }
可以堆叠多个:
#[MyAttribute('A')] #[MyAttribute('B')] class Test {}
或使用数组形式(PHP 8.0+):
#[MyAttribute('A'), MyAttribute('B')] class Test {}
你可以限制 Attribute 只能用在特定位置,通过 flags 参数:
#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)] class Route { public function __construct(public string $path) {} }
常用目标常量:
| 常量 | 说明 |
|---|---|
示例:只允许用于方法,并可重复:
使用 PHP 的反射 API 获取 Attributes:
$reflection = new ReflectionClass(MyClass::class); $attributes = $reflection->getAttributes(); foreach ($attributes as $attribute) { // 获取 Attribute 实例 $instance = $attribute->newInstance(); echo $instance->value; // 输出 'Hello' }
⚠️ 注意:
newInstance()会实例化 Attribute 类,因此构造函数参数必须匹配。
也可以获取原始参数而不实例化:
$attr = $reflection->getAttributes(MyAttribute::class)[0]; $args = $attr->getArguments(); // ['Hello']
#[Attribute(Attribute::TARGET_PARAMETER)] class MaxLength { public function __construct(public int $length) {} } function greet(#[MaxLength(10)] string $name) { // 验证逻辑可通过反射在调用前执行,如果匹配失败抛出异常,正常方法中的逻辑先不执行 }
模仿框架中反射处理注解,(直接实例化调用greet方法,注解是完全失效的)
<?php #[Attribute(Attribute::TARGET_PARAMETER)] class MaxLength { public function __construct(public int $length) {} } function greet(#[MaxLength(10)] string $name, string $message) { echo "Hello, {$name}! Message: {$message}\n"; } /** * 通用的函数参数注解校验函数(优化版:显式判断注解是否存在) * @param string $funcName 要调用的函数名 * @param array $args 函数入参数组(按参数顺序传递) * @throws InvalidArgumentException 校验失败时抛出异常 */ function validateFunctionArgs(string $funcName, array $args): void { $reflectionFunc = new ReflectionFunction($funcName); $parameters = $reflectionFunc->getParameters(); foreach ($parameters as $paramIndex => $param) { // 1. 跳过无传入值的参数 if (!isset($args[$paramIndex])) { continue; } // 2. 显式获取 MaxLength 注解,判断是否存在 $maxLengthAttributes = $param->getAttributes(MaxLength::class); // 核心优化:显式判断注解是否存在,不存在则直接跳过当前参数 if (empty($maxLengthAttributes)) { continue; } // 3. 注解存在时,才执行校验逻辑 /** @var MaxLength $maxLengthAttr */ $maxLengthAttr = $maxLengthAttributes[0]->newInstance(); $maxLength = $maxLengthAttr->length; $paramValue = $args[$paramIndex]; // 4. 仅对字符串类型参数做长度校验(避免非字符串参数报错) if (is_string($paramValue) && mb_strlen($paramValue) > $maxLength) { throw new InvalidArgumentException( "参数「{$param->getName()}」长度不能超过 {$maxLength}(当前长度:" . mb_strlen($paramValue) . ")" ); } } } function callFunctionWithValidation(string $funcName, array $args): void { validateFunctionArgs($funcName, $args); call_user_func_array($funcName, $args); } // -------------------------- 测试示例(验证无注解参数跳过) -------------------------- try { // 测试:name加了注解(长度限制10),message无注解(长度超10也不校验) callFunctionWithValidation('greet', ['Alice', '这是一段超过10个字符的消息内容']); // 测试:name长度超10,触发校验异常 callFunctionWithValidation('greet', ['ThisIsALongName123', '正常消息']); } catch (InvalidArgumentException $e) { echo "校验失败:{$e->getMessage()}\n"; }
#[Attribute(Attribute::TARGET_METHOD)] class Route { public function __construct( public string $path, public string $method = 'GET' ) {} } class UserController { #[Route('/user', 'GET')] public function list() {} }
路由解析器可通过反射读取 Route 属性注册路由。(具体可以看看下面引用的文章)
#[Attribute(Attribute::TARGET_PROPERTY)] class Column { public function __construct( public string $type, public bool $nullable = false ) {} } class User { #[Column('string', nullable: false)] public string $email; }
ORM 框架可在启动时扫描这些属性生成数据库映射。
| 特性 | DocBlock 注解 | PHP Attributes |
|---|---|---|
Route, Cacheable, ValidateEmail)。TARGET_* 限制使用位置,避免误用。PHP Attributes 是现代 PHP 开发的重要工具,它:
如果你正在使用 PHP 8+,强烈建议在新项目中优先使用 Attributes 替代传统注解。
📚 官方文档参考:
文档有千问生成
引用 :https://www.cnblogs.com/catchadmin/p/19395584
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。