当前位置: 首页 > 图文教程 > 网络编程 > PHP > PHP Tokenizer 学习笔记

PHP
PHP技巧:详解phplib模板使用过程及运行原理
PHP技巧:Smarty+adodb分页示例
PHP技巧:PHP脚本中关于拼写检查函数库
PHP技巧:PHP脚本编程中的文件系统函数库
PHP技巧:PHP中几种删除目录的三种方法
学习PHP技术:txtSQL安装手册中文版
学习PHP:PHP的通用检测函数总结
详细学习PHP中对文件和目录的操作方法
PHP+MYSQL实例:网站在线人数的程序代码
Linux操作系统启动httpd失败的解决方法
初学:在PHP开发中如何使用Session?
PHP初学者遇到的中文乱码解决方案
PHP实例:实现文件上传的程序源码
PHP实例:常用的数值判断函数
PHP实例源代码:PHP实现翻页处理的类
PHP实例:从数组里筛选出重复的数据
PHP实例:用PHP实现windows风格的树型菜单
PHP实例程序:实现给上传图片加水印图案的做法
PHP实例:用PHP编写的网上调查投票系统
PHP实例:一个非常全面获取图象信息的PHP函数

PHP Tokenizer 学习笔记


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-08-14   浏览: 115 ::
收藏到网摘: n/a

简述

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

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

实例

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

下面是个简单的实例,说明如何使用这两个函数:

以下为引用的内容:

$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]); }
}

对应的输出为

以下为引用的内容:

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 ?>

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

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

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

以下为引用的内容:

/** * “压缩”PHP 源代码 * * @see http://c7y.phparch.com/c/entry/1/art,practical_uses_tokenizer */
class CompactCode
{ static protected $out; static protected $tokens; static public function compact($source) { // 解析 PHP 源代码 self::$tokens = token_get_all($source); self::$out = ''; reset(self::$tokens); // 递归判断每个标记符的类型 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; } next(self::$tokens); } return self::$out; } 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; } } }
}

调用方式很简单,只需要使用

以下为引用的内容:

CompactCode::compact($source_code);

即可,返回的字符串就是压缩以后的内容。在这里还有更多使用 Tokenizer 的实例,推荐阅读