PHP Parser(PHP 解析器)
这是一个用 PHP 编写的 PHP 解析器。其目的是简化静态代码分析和操作。
版本 5.x 的文档(当前;用于在 PHP >= 7.4 上运行;用于解析 PHP 7.0 至 PHP 8.3,对 PHP 5.x 的解析支持有限)。
版本 4.x 的文档 (支持;用于在 PHP >= 7.0 上运行;用于解析 PHP 5.2 至 PHP 8.3).
特性
该库提供的主要功能是:
- 将 PHP 7 和 PHP 8 代码解析为抽象语法树(AST)。
- 无效的代码可以解析为部分 AST。
 - AST 包含准确的位置信息。
 
 - 以人类可读的形式转储 AST。
 - 将 AST 转换回 PHP 代码。
- 实验性:可以保留部分更改的 AST 的格式。
 
 - 遍历和修改 AST 的基础结构。
 - 命名空间名称的解析。
 - 常量表达式的评估。
 - 简化 AST 构建的代码生成器。
 - 将 AST 转换为 JSON 并返回。
 
快速开始
使用composer安装库:
php composer.phar require nikic/php-parser
将一些 PHP 代码解析为 AST 并以人类可读的形式转储结果:
<?php
use PhpParser\Error;
use PhpParser\NodeDumper;
use PhpParser\ParserFactory;
$code = <<<'CODE'
<?php
function test($foo)
{
    var_dump($foo);
}
CODE;
$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
try {
    $ast = $parser->parse($code);
} catch (Error $error) {
    echo "Parse error: {$error->getMessage()}\n";
    return;
}
$dumper = new NodeDumper;
echo $dumper->dump($ast) . "\n";
这将转储一个看起来像这样的 AST:
array(
    0: Stmt_Function(
        byRef: false
        name: Identifier(
            name: test
        )
        params: array(
            0: Param(
                type: null
                byRef: false
                variadic: false
                var: Expr_Variable(
                    name: foo
                )
                default: null
            )
        )
        returnType: null
        stmts: array(
            0: Stmt_Expression(
                expr: Expr_FuncCall(
                    name: Name(
                        parts: array(
                            0: var_dump
                        )
                    )
                    args: array(
                        0: Arg(
                            value: Expr_Variable(
                                name: foo
                            )
                            byRef: false
                            unpack: false
                        )
                    )
                )
            )
        )
    )
)
让我们遍历 AST 并执行某种修改。 例如,删除所有功能体:
use PhpParser\Node;
use PhpParser\Node\Stmt\Function_;
use PhpParser\NodeTraverser;
use PhpParser\NodeVisitorAbstract;
$traverser = new NodeTraverser();
$traverser->addVisitor(new class extends NodeVisitorAbstract {
    public function enterNode(Node $node) {
        if ($node instanceof Function_) {
            // Clean out the function body
            $node->stmts = [];
        }
    }
});
$ast = $traverser->traverse($ast);
echo $dumper->dump($ast) . "\n";
这为我们提供了一个 AST,其中 Function_::$stmts 为空:
array(
    0: Stmt_Function(
        byRef: false
        name: Identifier(
            name: test
        )
        params: array(
            0: Param(
                type: null
                byRef: false
                variadic: false
                var: Expr_Variable(
                    name: foo
                )
                default: null
            )
        )
        returnType: null
        stmts: array(
        )
    )
)
最后,我们可以将新的 AST 转换回 PHP 代码:
use PhpParser\PrettyPrinter; $prettyPrinter = new PrettyPrinter\Standard; echo $prettyPrinter->prettyPrintFile($ast);
这给出了我们的原始代码,减去了函数内部的 var_dump() 调用:
<?php
function test($foo)
{
}
文档
组件文档:
- Walking the AST
- Node visitors
 - Modifying the AST from a visitor
 - Short-circuiting traversals
 - Interleaved visitors
 - Simple node finding API
 - Parent and sibling references
 
 - Name resolution
- Name resolver options
 - Name resolution context
 
 - Pretty printing
- Converting AST back to PHP code
 - Customizing formatting
 - Formatting-preserving code transformations
 
 - AST builders
- Fluent builders for AST nodes
 
 - Lexer
- Lexer options
 - Token and file positions for nodes
 - Custom attributes
 
 - Error handling
- Column information for errors
 - Error recovery (parsing of syntactically incorrect code)
 
 - Constant expression evaluation
- Evaluating constant/property/etc initializers
 - Handling errors and unsupported expressions
 
 - JSON representation
- JSON encoding and decoding of ASTs
 
 - Performance
- Disabling XDebug
 - Reusing objects
 - Garbage collection impact
 
 - Frequently asked questions
- Parent and sibling references
 
 
(The first version translated by vz on 2020.07.26)