Как использовать PHP -Parser, чтобы получить имя глобальной переменной и изменить его - PullRequest
2 голосов
/ 29 февраля 2020

Я хочу использовать библиотеку PHP -Parser , чтобы получить глобальный метод (_POST, _GET, _REQUEST) для получения значений в PHP. Я использую PHP -Parser , где я хочу проверить имя узла, если оно равно (_POST, _GET, _REQUEST). Я все еще новичок в PHP -Parser и не понимаю, как получить эти глобальные переменные. Например, если у меня есть следующий исходный код:

code:

<?php 
$firstname = $_POST['firstname];

PHP -парсер, который я использовал до сих пор, выглядит так:

<?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 -парсер 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 ) ) )
  1. Как определить, есть ли в коде теста _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!"; 

Спасибо за помощь

1 Ответ

1 голос
/ 29 февраля 2020

Это должно работать для конкретного выделенного вами экземпляра, он работает только с экземпляром 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!';
...