php注释,命名空间和使用关键字

时间:2014-07-03 09:52:00

标签: php symfony namespaces annotations

我正在为php编写一个注释解析器(由于特定需要,我不能使用任何第三方解析器)并且我将sympfony2代码作为灵感来源

namespace Acme\StoreBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="product")
 */
class Product
{
    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

正如我在这里看到的,我们在use语句中定义ORM然后以某种方式注释解析器知道ORM是Doctrine \ ORM \ Mapping的别名。

我的最终目标是能够将类名作为别名传递到我的注释中

use some/namespace/Enum;
use another/ns/PropEnum;

class Abc
{
   /**
    * @Enum(PropEnum)
    **/
   protected $prop;
}

请你指出我正确的方向,因为我甚至不知道从哪里开始?

由于

1 个答案:

答案 0 :(得分:3)

让我们来看看doctrine/annotations(Symfony使用的包)如何解决这个问题。

PhpParser解析类的PHP文件(可以通过ReflectionClass#getFilename()获得)。让我们逐行查看parseClass()方法:

if (method_exists($class, 'getUseStatements')) {
    return $class->getUseStatements();
}

Doctrine有一个自定义StaticReflectionClass类,它已经有一个getUseStatements()方法来获取类文件中的use语句。我假设你没有使用那个课程,所以让我们继续前进!

if (false === $filename = $class->getFilename()) {
    return array();
}

$content = $this->getFileContent($filename, $class->getStartLine());

if (null === $content) {
    return array();
}

这些语句检索类的文件内容。如果没有内容或没有文件,也没有使用声明。

$namespace = preg_quote($class->getNamespaceName());
$content = preg_replace('/^.*?(\bnamespace\s+' . $namespace . '\s*[;{].*)$/s', '\\1', $content);

在这里,他们正在寻找定义文件中类的命名空间的行。接下来是use语句,因此正则表达式只提取命名空间及其后的所有内容。

$tokenizer = new TokenParser('<?php ' . $content);

$statements = $tokenizer->parseUseStatements($class->getNamespaceName());

return $statements;

然后它创建一个TokenParser类,其中只包含该内容,并让它在其中找到use语句。

如果查看TokenParser,您会发现它使用token_get_all()将文件转换为PHP引擎使用的PHP令牌,然后只需移动该令牌树查找{{ 1}}语句,它提取并保存。