使用反射可以轻松获取源文件中方法的起始和结束行,例如:ReflectionFunctionAbstract::getFileName()
、ReflectionFunctionAbstract::getStartLine()
和 ReflectionFunctionAbstract::getEndLine()
提供了这种功能。然而,对于属性似乎不起作用。在类定义中提取至少属性声明的起始行和文件名的最佳方法是什么?
使用反射可以轻松获取源文件中方法的起始和结束行,例如:ReflectionFunctionAbstract::getFileName()
、ReflectionFunctionAbstract::getStartLine()
和 ReflectionFunctionAbstract::getEndLine()
提供了这种功能。然而,对于属性似乎不起作用。在类定义中提取至少属性声明的起始行和文件名的最佳方法是什么?
这并不是微不足道的,但也不太难。
您可以通过反射获取定义属性的类。然后,您可以从那里获取文件名。然后,您只需对文件进行分词,并检查属性声明所在的行,或逐行遍历文件并进行字符串匹配即可。
以下是可能的一种方法:
$reflector = new ReflectionProperty('Foo', 'bar');
$declaringClass = $reflector->getDeclaringClass();
$classFile = new SplFileObject($declaringClass->getFileName());
foreach ($classFile as $line => $content) {
if (preg_match(
'/
(private|protected|public|var) # match visibility or var
\s # followed 1 whitespace
\$bar # followed by the var name $bar
/x',
$content)
) {
echo $line + 1;
}
}
这里有一个演示以证明它有效
显然,以上解决方案假设属性以某种方式声明。它还假定您的每个文件都有一个类。如果您不能确定这是正确的情况,则记号化是更好的选择。但它也更加困难。
$classInfo = (new BetterReflection())
->reflector()
->reflectClass($class);
foreach ( $classInfo->getProperties() as $reflectionProperty) {
$declaringClass = $reflectionProperty->getDeclaringClass()->getFileName();
$declaringSource = $reflectionProperty->getDeclaringClass()->getLocatedSource()->getSource();
$sourceLines = explode("\n", $declaringSource);
$propertySource = join("\n", array_slice($sourceLines, $reflectionProperty->getStartLine(), $reflectionProperty->getEndLine()-$reflectionProperty->getStartLine()));
$properties[$reflectionProperty->getName()] = [
'declaringClass' => $declaringClass,
'source' => $propertySource,
'startLine' => $reflectionProperty->getStartLine(),
'endLine' => $reflectionProperty->getEndLine()
];
}
print_r($properties);