html5中文学习网

您的位置: 首页 > 网络编程 > PHP编程 » 正文

PHP - Tokenizer的学习经验分享_PHP教程_编程技术

[ ] 已经帮助:人解决问题
在某个项目中需要分析 PHP 代码,分离出对应的函数调用(以及源代码对应的位置)。虽然这使用正则也可以实现,但无论从效率还是代码复杂度方面考虑,这都不是最优的方式。

在某个项目中需要分析 PHP 代码,分离出对应的函数调用(以及源代码对应的位置)。虽然这使用正则也可以实现,但无论从效率还是代码复杂度方面考虑,这都不是最优的方式。Y93HTML5中文学习网 - HTML5先行者学习网

查询了 PHP 手册,发现其实 PHP 已经内置解析器的接口,那就是 PHP Tokenizer,这工具正是我想要的。使用 PHP Tokenizer 能简单、高效、准确的分析出 PHP 源代码的组成。Y93HTML5中文学习网 - HTML5先行者学习网

实例Y93HTML5中文学习网 - HTML5先行者学习网

官方站点对 Tokenizer 的文档很少,不过这不影响我们理解它。Tokenizer 组件仅仅包含两个函数:token_get_all 以及 token_name,它们分别用于分析 PHP 代码以及获取代码对应的标识符名称。Y93HTML5中文学习网 - HTML5先行者学习网

下面是个简单的实例,说明如何使用这两个函数:Y93HTML5中文学习网 - HTML5先行者学习网

以下为引用的内容:Y93HTML5中文学习网 - HTML5先行者学习网

$code = '<?php echo "string1"."string2"; ?>';
$tokens = token_get_all($code);
foreach ($tokens as $token) {
    if (is_array($token)) {
        // 行号、标识符字面量、对应内容
        printf("%d - %s/t%s/n", $token[2], token_name($token[0]), $token[1]);
    }
}Y93HTML5中文学习网 - HTML5先行者学习网


对应的输出为Y93HTML5中文学习网 - HTML5先行者学习网

以下为引用的内容:Y93HTML5中文学习网 - HTML5先行者学习网

1 - T_OPEN_TAG    <?php
1 - T_ECHO    echo
1 - T_WHITESPACE    
1 - T_CONSTANT_ENCAPSED_STRING    "string1"
1 - T_CONSTANT_ENCAPSED_STRING    "string2"
1 - T_WHITESPACE    
1 - T_CLOSE_TAG    ?>Y93HTML5中文学习网 - HTML5先行者学习网


这里顺便说明下,$token 如果为数组,那么分别对应的三个数组成员为 token 标识符(可以用 token_name 获得字面量)、对应的源代码内容、以及对应的行号。Y93HTML5中文学习网 - HTML5先行者学习网

还有中情况就是 $token 为字符串,这可能的情况之一就是为 T_CONSTANT_ENCAPSED_STRING 等常量,在分析代码时要注意。如果对这点很在意,可以考虑使用这里的代码。Y93HTML5中文学习网 - HTML5先行者学习网

是的,调用方式非常的简单,我们的野心当然远远要比写个简单的循环要大得多。我们可以利用这个组件做写实事,例如下面的代码用于“压缩” PHP 代码,去除不不要的换行、空白以及注释Y93HTML5中文学习网 - HTML5先行者学习网

以下为引用的内容:Y93HTML5中文学习网 - HTML5先行者学习网

/**
 * “压缩”PHP 源代码
 *
 * @see http://c7y.phparch.com/c/entry/1/art,practical_uses_tokenizer
 */
class CompactCode
{
    static protected $out;
    static protected $tokens;Y93HTML5中文学习网 - HTML5先行者学习网

    static public function compact($source)
    {
        // 解析 PHP 源代码
        self::$tokens = token_get_all($source);  
        self::$out = '';Y93HTML5中文学习网 - HTML5先行者学习网

        reset(self::$tokens);Y93HTML5中文学习网 - HTML5先行者学习网

        // 递归判断每个标记符的类型
        while ($t = current(self::$tokens)) {
            if (is_array($t)) {
                // 过滤空白、注释
                if ($t[0] == T_WHITESPACE $t[0] == T_DOC_COMMENT $t[0] == T_COMMENT) {
                    self::skipWhiteAndComments();
                    continue;
                }      
                self::$out .= $t[1];
            } else {
                self::$out .= $t;
            }Y93HTML5中文学习网 - HTML5先行者学习网

            next(self::$tokens);
        }Y93HTML5中文学习网 - HTML5先行者学习网

        return self::$out;
    }Y93HTML5中文学习网 - HTML5先行者学习网

    static private function skipWhiteAndComments()
    {
        // 增加个空格,用于分割关键字
        self::$out .= ' ';
        while ($t = current(self::$tokens)) {
            // 再次贪婪查找
            if (is_array($t) && ($t[0] == T_WHITESPACE $t[0] == T_DOC_COMMENT $t[0] == T_COMMENT)) {
                next(self::$tokens);
            } else {
                return;
            }
        }
    }
}Y93HTML5中文学习网 - HTML5先行者学习网


调用方式很简单,只需要使用Y93HTML5中文学习网 - HTML5先行者学习网

以下为引用的内容:Y93HTML5中文学习网 - HTML5先行者学习网

CompactCode::compact($source_code);
 Y93HTML5中文学习网 - HTML5先行者学习网


即可,返回的字符串就是压缩以后的内容。
 Y93HTML5中文学习网 - HTML5先行者学习网

Y93HTML5中文学习网 - HTML5先行者学习网
Y93HTML5中文学习网 - HTML5先行者学习网
(责任编辑:)
推荐书籍
推荐资讯
关于HTML5先行者 - 联系我们 - 广告服务 - 友情链接 - 网站地图 - 版权声明 - 人才招聘 - 帮助