duanqin9507 2014-07-03 09:51
浏览 44
已采纳

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

I am writing an annotation parser for php (I cannot used any 3rd party ones due to specific needs) and I took sympfony2 code as an inspiration

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;

As I can see here we define ORM in use statement and then somehow the annotation parser knows that ORM is an alias to Doctrine\ORM\Mapping.

My ultimate goal is to be able to pass class names as aliases into my annotations

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

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

Could you please point me towards the right direction as I do not even know where to start?

Thanks

  • 写回答

1条回答 默认 最新

  • duandian8110 2014-07-03 11:27
    关注

    Let's take a look at how doctrine/annotations (the package used by Symfony) solves this problem.

    The PhpParser parses the PHP file of the class (which you can get by ReflectionClass#getFilename()). Let's look at the parseClass() method line by line:

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

    Doctrine has a custom StaticReflectionClass class which already has a getUseStatements() method to get the use statements in the class file. I assume you don't use that class, so let's move on!

    if (false === $filename = $class->getFilename()) {
        return array();
    }
    
    $content = $this->getFileContent($filename, $class->getStartLine());
    
    if (null === $content) {
        return array();
    }
    

    These statements retrieve the file content of the class. If there was no content or no file, there are also no use statements.

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

    Here they are looking for the line that defines the namespace for the class in the file. It'll be followed by the use statements, so the regex just extracts the namespace and everything that follows it.

    $tokenizer = new TokenParser('<?php ' . $content);
    
    $statements = $tokenizer->parseUseStatements($class->getNamespaceName());
    
    return $statements;
    

    Then it creates a TokenParser class with only that content in it and let it find the use statements in it.

    If you look at the TokenParser, you'll find that it uses token_get_all() to transform the file into PHP tokens used by the PHP engine and then just moves through that token tree looking for T_USE statements, which it extracts and saves.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 python中transformers可以正常下载,但是没有办法使用pipeline
  • ¥50 分布式追踪trace异常问题
  • ¥15 人在外地出差,速帮一点点
  • ¥15 如何使用canvas在图片上进行如下的标注,以下代码不起作用,如何修改
  • ¥15 Windows 系统cmd后提示“加载用户设置时遇到错误”
  • ¥50 vue router 动态路由问题
  • ¥15 关于#.net#的问题:End Function
  • ¥15 无法import pycausal
  • ¥15 weditor无法连接模拟器Local server not started, start with?
  • ¥20 6-3 String类定义