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

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 PADS Logic 原理图
  • ¥15 PADS Logic 图标
  • ¥15 电脑和power bi环境都是英文如何将日期层次结构转换成英文
  • ¥15 DruidDataSource一直closing
  • ¥20 气象站点数据求取中~
  • ¥15 如何获取APP内弹出的网址链接
  • ¥15 wifi 图标不见了 不知道怎么办 上不了网 变成小地球了
  • ¥50 STM32单片机传感器读取错误
  • ¥50 power BI 从Mysql服务器导入数据,但连接进去后显示表无数据