PHP反射:获取常量的文档注解

3lxsmp7m  于 2023-06-28  发布在  PHP
关注(0)|答案(2)|浏览(134)

很容易检索方法和属性的文档注解。但是常量呢?没有ReflectionConstant类允许我在它们上调用getDocComment()。可以使用ReflectionClass::getConstants获取常量列表及其值作为字符串,但仅此而已。是否有变通方案?

qpgpyjmq

qpgpyjmq1#

据我所知,没有内置的函数或类允许您检索类常量doc注解。但是,您可以使用token_get_all($classContent)并编写自己的解析器。
以下是我在需要这个功能之后提出的:

/**
 * Simple DocComment support for class constants.
 */
class ConstDoc
{
    /** @var array Constant names to DocComment strings. */
    private $docComments = [];

    /** Constructor. */
    public function __construct($clazz)
    {
        $this->parse(new \ReflectionClass($clazz));
    }

    /** Parses the class for constant DocComments. */
    private function parse(\ReflectionClass $clazz)
    {
        $content = file_get_contents($clazz->getFileName());
        $tokens = token_get_all($content);

        $doc = null;
        $isConst = false;
        foreach($tokens as $token)
        {
            if (!is_array($token) || count($token) <= 1)
            {
                continue;
            }

            list($tokenType, $tokenValue) = $token;

            switch ($tokenType)
            {
                // ignored tokens
                case T_WHITESPACE:
                case T_COMMENT:
                    break;

                case T_DOC_COMMENT:
                    $doc = $tokenValue;
                    break;

                case T_CONST:
                    $isConst = true;
                    break;

                case T_STRING:
                    if ($isConst)
                    {
                        $this->docComments[$tokenValue] = self::clean($doc);
                    }
                    $doc = null;
                    $isConst = false;
                    break;

                // all other tokens reset the parser
                default:
                    $doc = null;
                    $isConst = false;
                    break;
            }
        }
    }

    /** Returns an array of all constants to their DocComment. If no comment is present the comment is null. */
    public function getDocComments()
    {
        return $this->docComments;
    }

    /** Returns the DocComment of a class constant. Null if the constant has no DocComment or the constant does not exist. */
    public function getDocComment($constantName)
    {
        if (!isset($this->docComments) || !isset($this->docComments[$constantName]))
        {
            return null;
        }

        return $this->docComments[$constantName];
    }

    /** Cleans the doc comment. Returns null if the doc comment is null. */
    private static function clean($doc)
    {
        if ($doc === null)
        {
            return null;
        }

        $result = null;
        $lines = preg_split('/\R/', $doc);
        foreach($lines as $line)
        {
            $line = trim($line, "/* \t\x0B\0");
            if ($line === '')
            {
                continue;
            }

            if ($result != null)
            {
                $result .= ' ';
            }
            $result .= $line;
        }
        return $result;
    }
}
t9eec4r0

t9eec4r02#

现在有一个API,你需要使用getReflectionConstants而不是getConstants来访问所有额外的元数据:

class Foo {
    /** I am a comment */
    const BAR = "bar";

    /** Other comment */
    const BAZ = "baz";
}

$rc = new ReflectionClass(Foo::class);
foreach($rc->getReflectionConstants() as $rcc) {
    print("{$rcc->getName()} ({$rcc->getValue()}) - {$rcc->getDocComment()}\n");
}

哪些打印:

BAR (bar) - /** I am a comment */
BAZ (baz) - /** Other comment */

相关问题