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 求差集那个函数有问题,有无佬可以解决
  • ¥15 【提问】基于Invest的水源涵养
  • ¥20 微信网友居然可以通过vx号找到我绑的手机号
  • ¥15 寻一个支付宝扫码远程授权登录的软件助手app
  • ¥15 解riccati方程组
  • ¥15 display:none;样式在嵌套结构中的已设置了display样式的元素上不起作用?
  • ¥15 使用rabbitMQ 消息队列作为url源进行多线程爬取时,总有几个url没有处理的问题。
  • ¥15 Ubuntu在安装序列比对软件STAR时出现报错如何解决
  • ¥50 树莓派安卓APK系统签名
  • ¥65 汇编语言除法溢出问题