如何使用PHP-Parser获取全局变量名并修改
How to use PHP-Parser to get the global variables name and change it
我想在我想检查节点名称是否等于 (_POST, _GET, _REQUEST
) 的地方使用 PHP-Parser library to get the global method (_POST, _GET, _REQUEST
) to get values in PHP. I'm using PHP-Parser。我仍然是 PHP-Parser 的初学者,不知道如何获取这些全局变量。例如,如果我有以下源代码:
代码:
<?php
$firstname = $_POST['firstname];
我目前使用的 PHP-parser 如下所示:
<?php
require_once('vendor/autoload.php');
use PhpParser\Error;
use PhpParser\NodeDumper;
use PhpParser\ParserFactory;
$code = <<<'CODE'
<?php
$firstname= $_POST['firstname'];
CODE;
$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
try {
$ast = $parser->parse($code);
} catch (Error $error) {
echo "Parse error: {$error->getMessage()}\n";
return;
}
use PhpParser\{Node, NodeTraverser, NodeVisitorAbstract};
$traverser = new NodeTraverser;
// This code exist in the PHP-Parser documentation
$traverser->addVisitor(new class extends NodeVisitorAbstract {
public function leaveNode(Node $node) {
if ($node instanceof Node\Stmt\Expression
&& $node->expr instanceof Node\Expr\FuncCall
&& $node->expr->name instanceof Node\Name
&& $node->expr->name->toString() === '_POST'
) {
// Change the $_POST['firstname'] and replace it with XXX value
}
}
});
print_r($modifiedStmts = $traverser->traverse($ast) );
执行上面的 PHP-Parser AST 后,我得到以下结果:
Array ( [0] => PhpParser\Node\Stmt\Expression Object ( [expr] => PhpParser\Node\Expr\Assign Object ( [var] => PhpParser\Node\Expr\Variable Object ( [name] => firstname [attributes:protected] => Array ( [startLine] => 2 [endLine] => 2 ) ) [expr] => PhpParser\Node\Expr\ArrayDimFetch Object ( [var] => PhpParser\Node\Expr\Variable Object ( [name] => _POST [attributes:protected] => Array ( [startLine] => 2 [endLine] => 2 ) ) [dim] => PhpParser\Node\Scalar\String_ Object ( [value] => firstname [attributes:protected] => Array ( [startLine] => 2 [endLine] => 2 [kind] => 1 ) ) [attributes:protected] => Array ( [startLine] => 2 [endLine] => 2 ) ) [attributes:protected] => Array ( [startLine] => 2 [endLine] => 2 ) ) [attributes:protected] => Array ( [startLine] => 2 [endLine] => 2 ) ) )
- 如何检测测试代码是否有
_POST, _GET, REQUEST
?例如:
// Something like this
if($node->value === '_POST' OR $node->value === '_GET' or $node->value === '_REQUEST')
{
// Do next step to change the global variable to specific text value
}
- 如何将
$_POST[firstname]
更改为 hello world! or any text
值?例如:
之前
$firstname = $_POST['firstname'];
之后
$firstname = "hello World!";
感谢您的帮助
这应该适用于您突出显示的特定实例,它只适用于 POST 实例,但应该很容易扩展。
主要部分是当您看到代码的 AST 时,请尝试确保您可以识别 _POST
访问的基础。这原来是一个Node\Expr\ArrayDimFetch
,然后在这个里面你想检查它使用的变量是否是_POST
。
一旦你确定了这一点,你就可以用一个新的节点替换那个节点,它只是一个字符串 Node\Scalar\String_("Hello World!");
.
$traverser->addVisitor(new class extends NodeVisitorAbstract {
public function leaveNode(Node $node) {
if ($node instanceof Node\Expr\ArrayDimFetch
&& $node->var instanceof Node\Expr\Variable
&& $node->var->name === '_POST'
) {
// Change the $_POST['firstname'] and replace it with XXX value
return new Node\Scalar\String_("Hello World!");
}
}
});
$prettyPrinter = new PhpParser\PrettyPrinter\Standard;
echo $prettyPrinter->prettyPrintFile($traverser->traverse($ast));
来自你的原始代码
<?php
$firstname= $_POST['firstname'];
此代码输出....
<?php
$firstname = 'Hello World!';
我想在我想检查节点名称是否等于 (_POST, _GET, _REQUEST
) 的地方使用 PHP-Parser library to get the global method (_POST, _GET, _REQUEST
) to get values in PHP. I'm using PHP-Parser。我仍然是 PHP-Parser 的初学者,不知道如何获取这些全局变量。例如,如果我有以下源代码:
代码:
<?php
$firstname = $_POST['firstname];
我目前使用的 PHP-parser 如下所示:
<?php
require_once('vendor/autoload.php');
use PhpParser\Error;
use PhpParser\NodeDumper;
use PhpParser\ParserFactory;
$code = <<<'CODE'
<?php
$firstname= $_POST['firstname'];
CODE;
$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
try {
$ast = $parser->parse($code);
} catch (Error $error) {
echo "Parse error: {$error->getMessage()}\n";
return;
}
use PhpParser\{Node, NodeTraverser, NodeVisitorAbstract};
$traverser = new NodeTraverser;
// This code exist in the PHP-Parser documentation
$traverser->addVisitor(new class extends NodeVisitorAbstract {
public function leaveNode(Node $node) {
if ($node instanceof Node\Stmt\Expression
&& $node->expr instanceof Node\Expr\FuncCall
&& $node->expr->name instanceof Node\Name
&& $node->expr->name->toString() === '_POST'
) {
// Change the $_POST['firstname'] and replace it with XXX value
}
}
});
print_r($modifiedStmts = $traverser->traverse($ast) );
执行上面的 PHP-Parser AST 后,我得到以下结果:
Array ( [0] => PhpParser\Node\Stmt\Expression Object ( [expr] => PhpParser\Node\Expr\Assign Object ( [var] => PhpParser\Node\Expr\Variable Object ( [name] => firstname [attributes:protected] => Array ( [startLine] => 2 [endLine] => 2 ) ) [expr] => PhpParser\Node\Expr\ArrayDimFetch Object ( [var] => PhpParser\Node\Expr\Variable Object ( [name] => _POST [attributes:protected] => Array ( [startLine] => 2 [endLine] => 2 ) ) [dim] => PhpParser\Node\Scalar\String_ Object ( [value] => firstname [attributes:protected] => Array ( [startLine] => 2 [endLine] => 2 [kind] => 1 ) ) [attributes:protected] => Array ( [startLine] => 2 [endLine] => 2 ) ) [attributes:protected] => Array ( [startLine] => 2 [endLine] => 2 ) ) [attributes:protected] => Array ( [startLine] => 2 [endLine] => 2 ) ) )
- 如何检测测试代码是否有
_POST, _GET, REQUEST
?例如:
// Something like this
if($node->value === '_POST' OR $node->value === '_GET' or $node->value === '_REQUEST')
{
// Do next step to change the global variable to specific text value
}
- 如何将
$_POST[firstname]
更改为hello world! or any text
值?例如: 之前
$firstname = $_POST['firstname'];
之后
$firstname = "hello World!";
感谢您的帮助
这应该适用于您突出显示的特定实例,它只适用于 POST 实例,但应该很容易扩展。
主要部分是当您看到代码的 AST 时,请尝试确保您可以识别 _POST
访问的基础。这原来是一个Node\Expr\ArrayDimFetch
,然后在这个里面你想检查它使用的变量是否是_POST
。
一旦你确定了这一点,你就可以用一个新的节点替换那个节点,它只是一个字符串 Node\Scalar\String_("Hello World!");
.
$traverser->addVisitor(new class extends NodeVisitorAbstract {
public function leaveNode(Node $node) {
if ($node instanceof Node\Expr\ArrayDimFetch
&& $node->var instanceof Node\Expr\Variable
&& $node->var->name === '_POST'
) {
// Change the $_POST['firstname'] and replace it with XXX value
return new Node\Scalar\String_("Hello World!");
}
}
});
$prettyPrinter = new PhpParser\PrettyPrinter\Standard;
echo $prettyPrinter->prettyPrintFile($traverser->traverse($ast));
来自你的原始代码
<?php
$firstname= $_POST['firstname'];
此代码输出....
<?php
$firstname = 'Hello World!';