PHP Tokenizer的实际和日常使用示例是什么?
有没有人用过这个?
答案 0 :(得分:17)
我使用PHP_CodeSniffer编码样式合规性,它是在tokeniser上构建的。此外,一些框架(例如Symfony 2)使用tokeniser来生成PHP代码的缓存文件或中间类文件。也可以使用tokeniser来构建源代码格式化程序或语法高亮显示器。
基本上,只要您将PHP代码用作数据,就可以使用tokeniser。尝试使用正则表达式或其他字符串处理函数解析PHP代码更加可靠。
答案 1 :(得分:16)
我个人已经用它来构建PHP sandbox,它试图为执行PHP脚本创建一个更安全的环境。
此外,我做了很多实验来预处理PHP,例如我有一个(不完整的)PHP 5.3模拟器,用于PHP 5.2,名为prephp。
许多其他类似工具,例如源代码分析器(用于security auditing,code style分析,...)也使用Tokenizer。
但即使对于较小的东西,Tokenizer也可能很方便。不仅仅是大规模的代码分析器。例如,如果您接受PHP数组并想要检查它是否是恶意的,您可以do so using the Tokenizer。
PS:目前我正在切换到实际解析PHP,而不仅仅是使用我最近发布的PHP parser written in PHP来标记它(它有效,但实际上还没有实用)。答案 2 :(得分:11)
有趣的问题。
我自己还没有在任何生产项目中使用过标记器,但是有一些关于Stack Overflow的问题,令牌化器是(或至少一个)正确答案。
Automatically parsing PHP to separate PHP code from HTML - 从PHP代码中提取注释,例如构建文档(phpDocumentor以这种方式工作)
Class exists in an external file - 分析代码,查看某个类是否存在于文件中(例如,对于插件管理系统)
Permanently write variables to a php file with php - 改变PHP源代码文件,例如填写配置变量。使用tokenizer是在解析器级别上执行此操作的第一步。
How to create a list of all built-in PHP functions a project makes use of? - 分析PHP项目中使用的函数
答案 3 :(得分:3)
一个非常基本的用法是语法高亮。
foreach(token_get_all($source) as $token) {
if (is_array($token))
{
$map = "token_name";
echo "<span class={$map($token[0])}>$token[1]</span>";
}
else {
echo "<span class=T_RAW>$token</span>";
}
}
当然,令牌编号通常会转换为更好的CSS类名,但您只需制作一个仅包含.T_COMMENT,.T_ARRAY,.T_ELSEIF,.T_FUNCTION ...类的样式表。
答案 4 :(得分:3)
我使用了tokenizer来查找回调复杂性数字以及回调的其他一些代码指标:
if ((isset($reflection) === true) && ($reflection->getFileName() !== false))
{
if (($source = file($reflection->getFileName(), FILE_IGNORE_NEW_LINES)) !== false)
{
$source = implode("\n", array_slice($source, $reflection->getStartLine() - 1, $reflection->getEndLine() - ($reflection->getStartLine() - 1)));
$result[$key]['source'] = array
(
'ccn' => 1,
'statements' => 0,
'lines' => array
(
'logical' => array(),
'physical' => substr_count($source, "\n"),
),
);
if (is_array($tokens = token_get_all(sprintf('<?php %s ?>', $source))) === true)
{
$points = array_map('constant', array_filter(array
(
'T_BOOLEAN_AND',
'T_BOOLEAN_OR',
'T_CASE',
'T_CATCH',
'T_ELSEIF',
'T_FINALLY',
'T_FOR',
'T_FOREACH',
'T_GOTO',
'T_IF',
'T_LOGICAL_AND',
'T_LOGICAL_OR',
'T_LOGICAL_XOR',
'T_WHILE',
), 'defined'));
foreach ($tokens as $token)
{
if (is_array($token) === true)
{
if ((in_array($token[0], array(T_CLOSE_TAG, T_COMMENT, T_DOC_COMMENT, T_INLINE_HTML, T_OPEN_TAG), true) !== true) && (strlen(trim($token[1])) > 0))
{
if (in_array($token[0], $points, true) === true)
{
++$result[$key]['source']['ccn'];
}
array_push($result[$key]['source']['lines']['logical'], $token[2]);
}
}
else if (strncmp($token, '?', 1) === 0)
{
++$result[$key]['source']['ccn'];
}
else if (strncmp($token, ';', 1) === 0)
{
++$result[$key]['source']['statements'];
}
}
$result[$key]['source']['lines']['logical'] = max(0, count(array_unique($result[$key]['source']['lines']['logical'])) - 1);
}
}
}
答案 5 :(得分:2)
我的一位朋友写了Überloader(PHP5的蛮力自动加载器。),它在索引类文件时使用了这种技术。来自它的_check_file()
method将是您特别感兴趣的。
Überloader专为未计划或考虑其类命名约定或文件结构的遗留项目而设计。
我每天都会在正在修理或翻新的旧项目中使用该课程。
答案 6 :(得分:2)
令牌化器功能非常好 强大。例如,你可以 检索给定的所有方法 使用如下算法的类:
每个令牌:如果令牌是T_FUNCTION 如果缓冲区启动,则启动缓冲区 然后将当前字符串添加到 如果令牌是缓冲区(停止缓冲区
)最棒的是班级 方法会有正确的情况,所以 这是一个很好的方式绕过 get_class_methods的限制 返回小写方法名称。也 因为你使用类似的算法 可以读取函数的参数 你可以实现类似反射 PHP4的功能。
最后,您可以将其用作更简单的方法 从一个提取Javadoc的方法 用于生成文档的类文件。 util / MethodTable.php类 AMFPHP(http://www.amfphp.org)使用 tokenizer函数创建一个 所有的方法表 参数,描述,返回类型, 等等,从那个方法表中就可以了 生成与之匹配的ActionScript PHP,但它也适合 生成JavaScript,文档 文件,或基本上你放的任何东西 你的想法。我也可以看到这个 可能是一个班级的基础 - &gt; WSDL 文件生成器。
您可以用于收集有关某些PHP代码的各种信息,例如所有已定义的类,方法,变量,生成文档和类似任务。
答案 7 :(得分:0)
我正在研究Symfony 1.2遗留应用程序,并使用tokenizer来获取sfConfig::get()
和sfConfig::set()
的所有调用。
所以基本上我记录了我的应用程序的所有配置参数。