PHP:如何优雅地将类/方法注释转换为多维数组?
优雅解析PHP注解为多维数组的方案
当然有靠谱的方法实现这个需求!核心思路是通过反射获取注释内容,用正则提取所有注解,最后把非标准的参数格式转换成目标数组。下面是具体的实现步骤和代码:
步骤1:获取类/方法的注释文本
PHP的Reflection扩展可以轻松拿到类、方法或属性的注释块。比如要解析某个方法的注释:
$reflectionMethod = new ReflectionMethod(YourClass::class, 'yourMethod'); $comment = $reflectionMethod->getDocComment();
步骤2:提取所有注解
用正则表达式匹配注释中所有以@开头的注解,拆分出注解名称和可选的参数部分:
preg_match_all('/@(\w+)(?:\((.*?)\))?/s', $comment, $matches, PREG_SET_ORDER);
这个正则会把每个注解拆成三部分:完整匹配结果、注解名称、参数内容(如果存在的话)。
步骤3:解析注解参数为数组
接下来要把非标准的参数格式(比如{'a'}、subValue:{a: 5})转换成PHP数组。我们先做格式替换,再安全解析:
- 把
{}替换成[],冒号:替换成=>,让参数符合PHP数组语法 - 用
eval(注意:仅在你能完全控制注解内容时使用,避免注入风险)或自定义解析器转换为数组
完整解析类示例
class AnnotationParser { public static function parse(string $comment): array { $result = []; preg_match_all('/@(\w+)(?:\((.*?)\))?/s', $comment, $matches, PREG_SET_ORDER); foreach ($matches as $match) { $name = $match[1]; $params = $match[2] ?? null; if (is_null($params)) { $result[$name] = null; continue; } // 转换参数格式为合法PHP数组语法 $phpParams = str_replace(['{', ':', '}'], ['[', '=>', ']'], $params); // 处理外层无包裹的情况,比如@Third(subValue:{a:5}) 转成 ['subValue' => ['a' =>5]] if (!str_starts_with($phpParams, '[')) { $phpParams = "[$phpParams]"; } // 安全解析(假设注解内容可信,否则建议用自定义语法解析器) eval("\$parsedParams = $phpParams;"); $result[$name] = $parsedParams; } return $result; } }
使用示例
假设你的方法注释是:
/** * @First * @Second({'a'}) * @Third(subValue:{a: 5}) */ public function testMethod() {}
调用解析方法:
$reflection = new ReflectionMethod(YourClass::class, 'testMethod'); $comment = $reflection->getDocComment(); $annotations = AnnotationParser::parse($comment); print_r($annotations);
输出结果完全符合你的期望:
Array ( [First] => [Second] => Array ( [0] => a ) [Third] => Array ( [subValue] => Array ( [a] => 5 ) ) )
注意事项
- 安全性:如果注解内容来自不可信来源,
eval会有注入风险,这时可以写一个简单的递归解析器来处理参数,避免执行未知代码。 - 格式一致性:确保注解参数的格式统一(比如所有嵌套结构都用
{},键值对用:),这样转换逻辑才能稳定工作。 - 扩展能力:如果需要支持更复杂的注解格式(比如带引号的字符串、多参数),可以扩展正则和转换逻辑。
内容的提问来源于stack exchange,提问作者Przemysław Kaczmarczyk
相关产品推荐
相关产品推荐

