简述

在某个项目中需要分析 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 的实例,推荐阅读。

php tokenizer获取所有类,PHP Tokenizer 学习笔记相关推荐

  1. Java转义工具类StringEscapeUtils的学习笔记

    Java转义工具类StringEscapeUtils的学习笔记 前言 ​ 在java.commons.lang3 的包中有许多方便好用的工具类,类似于处理字符串的StringUtils,处理日期的Da ...

  2. JDBCUtils工具类的基础学习笔记

    注:以下整理笔记来自自己的公众号,适合初学者一起探讨,我也是初学者! 创建一个实体类: package com.zx.bean;public class User {private int id;pr ...

  3. java中的枚举类与注解学习笔记

    java中的枚举和注解 01.枚举类的使用 1.1.枚举类的理解 1.2.自定义枚举类 1.3.使用enum关键字定义枚举类 1.4.Enum类中的常用方法 1.5.使用enum关键字定义的枚举类实现 ...

  4. 3.1常用类(java学习笔记)包装类及日期类

    一.包装类 java是一门面向对象的语言,秉承一切皆对象的思想. 可java中有一些基本数据类型并不是对象,有时可能需要将它们变为对象. 这时就需要用到我们的包装类了. 基本数据类型 包装类 int ...

  5. c++矩阵类_Python线性代数学习笔记——矩阵的基本运算和基本性质,实现矩阵的基本运算...

    当学习完矩阵的定义以后,我们来学习矩阵的基本运算,与基本性质 矩阵的基本运算:矩阵的加法,每一个对应元素相加,对应结果的矩阵 例子:矩阵A和矩阵B表示的是同学上学期和下学期的课程的成绩,两个矩阵相加就 ...

  6. js粘贴板为什么获取不到图片信息_JavaScript 学习笔记(3):图片库

    本文使用 Zhihu On VSCode 创作并发布 1. 为什么要使用图片库 可以把所有的图片都放到一个网页里,不过当图片过多时,会导致网页体积过大. 因此,为每张图片分别创建一个网页的解决方案. ...

  7. java类与对象 学习笔记

    类与对象 面向对象(Object Oriented) 一.面向对象 三大特性: 封装性:对象的成员属性和行为看做一个不可分割的整体,一些不想让外界看到的方法也隐藏起来 继承性:java是类的单继承,接 ...

  8. 构造函数怎么在主函数调用_C++ 虚基类及其派生类构造函数(学习笔记:第7章 12)...

    虚基类及其派生类构造函数[1] 建立对象时所指定的类称为最远派生类. 虚基类的成员是由最远派生类的构造函数通过调用虚基类的构造函数进行初始化的. 在整个继承结构中,直接或间接继承虚基类的所有派生类,都 ...

  9. python获取键盘输入_Python 3 学习笔记之——键盘输入和读写文件

    1. 键盘输入 Python提供了 input() 内置函数从标准输入读入一行文本,默认的标准输入是键盘.input 可以接收一个 Python 表达式作为输入,并将运算结果返回. str = inp ...

最新文章

  1. 云计算服务在小企业中的作用?
  2. codevs 1227 方格取数 2
  3. 8个试剂,其中一个有毒,最少多少只小白鼠能检测出有毒试剂——分而治之思想...
  4. 反骨仔的 2016 年度全文目录索引
  5. python多线程为什么要用队列_Python程序中的线程操作-线程队列
  6. C++ Maps MultiMaps
  7. P2212 [USACO14MAR]Watering the Fields S(最小生成树)
  8. 定时监控服务,告警,并启动服务
  9. 深度学习优化算法大全系列4:AdaGrad(Adaptive Gradient)
  10. 分布式框架开发环境部署
  11. bcc语料库下载_大数据背景下BCC语料库的研制_荀恩东
  12. 线性代数辅导讲义(第三章 向量)
  13. 衡量计算机储存容量的常用计量单位是,衡量存储器的单位是什么
  14. 有效 360 度反馈系统的关键
  15. Git push的常见用法
  16. 网络安全工程师从0单排日记-0
  17. matlab 判断变量是否存在_matlab:建立一个函数M文件,判断输入变量是否为0.求大神支招...
  18. 第四章 以太坊智能合约solidity介绍
  19. 营销模式转型 推进ICT业务规模发展
  20. int 类型怎么判断空

热门文章

  1. 序列化和反序列化(json和pickle)day18
  2. SSM项目连接远程Linux服务器的mysql 启动tomcat卡在了 Initializing Spring root WebApplicationContext...
  3. APM代码学习笔记1
  4. java笔记:熟练掌握线程技术---基础篇之解决资源共享的问题(中)--前篇
  5. Confluence 6 使用电子邮件可见
  6. 转:完整的最简单的谱聚类python代码
  7. 管理数据,应用程序和主机安全-A
  8. 两个iOS应用之间的跳转
  9. sigmoid函数的求导过程
  10. linux中判断语句,Linux--shel的if判断语句--05