0

nikic/PHP-Parser を使用して PHP コードを解析し、そこから変数の数を抽出しています。単一の PHP ファイルでこれを行うことができます。

これがコードです

<?php
use PhpParser\Error;
use PhpParser\ParserFactory;
use PhpParser\NodeDumper;
use PhpParser\NodeTraverser;
use PhpParser\Node;
use PhpParser\NodeVisitorAbstract;
use PhpParser\PrettyPrinter;

require __DIR__ . '/../vendor/autoload.php';

$code = <<<'CODE'
<?php
    $a = "test";
    $b = "base64_encode";
    $c = array();
    $a();
    array();
    assert($a);
CODE;

class ExtractVars extends NodeVisitorAbstract {
    private $prettyPrinter = null;
    private $variables = [];

    public function __construct() {
        $this->prettyPrinter = new PhpParser\PrettyPrinter\Standard;
    }

    public function leaveNode(Node $node) {
        if ( $node instanceof PhpParser\Node\Expr\Assign  ) {
                $assignVars = $this->extractVarRefs ( $node->var );
                var_dump($assignVars);
                // Get string of what assigned to actually is
                $assign = $this->prettyPrinter->prettyPrintExpr($node->var);
                var_dump($assign);
         }
    }

    private function extractVarRefs ( Node $node ) : array  {
        $variableList = [];
        // If it's a variable, store the name
        if ( $node instanceof PhpParser\Node\Expr\Variable )   {
            $variable = $this->prettyPrinter->prettyPrintExpr($node);
            $this->variables[] = $variable;
            $variableList[] = $variable;
        }
        // Look for any further variables in the node
        foreach ( $node->getSubNodeNames() as $newNodeName )   {
            $newNode = $node->$newNodeName;
            if ( $newNode instanceof Node && $newNode->getSubNodeNames())   {
                // Recursive call to extract variables
                $toAdd = $this->extractVarRefs ( $newNode );
                // Add new list to current list
                $variableList = array_merge($variableList, $toAdd);
            }
        }
        return $variableList;
    }

    public function getVariables() : int  {
        return count(array_unique($this->variables));
    }
}

$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
$stmts = $parser->parse($code);
$traverser = new NodeTraverser;
$varExtract = new ExtractVars();
$traverser->addVisitor($varExtract);
$ast = $traverser->traverse($stmts);
print_r($varExtract->getVariables());

LeaveNode が検出した変数名を格納するために、配列 "$variables" を定義します。


これで、単一の PHP ファイルを使用できなくなりました。この Visitor.php は、初期化コードの最後の数行を保持しません。メイン ファイルで初期化して、配列の値を取得する必要があります。このような

//main.php
$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
$stmts = $parser->parse($code);
$traverser = new NodeTraverser;
$traverser->addVisitor($VisitorClassName);
$ast = $traverser->traverse($stmts);

//XXvisitor.php
<?php
use PhpParser\Node;
use PhpParser\NodeVisitorAbstract;

class Visitor extends NodeVisitorAbstract
{
    public function leaveNode(Node $node)
    {
      
    }
}

私は 1 つの php ファイルを作成しただけで、プロジェクトの開発は行っていません。メインファイルから配列に格納されている変数名を取得するにはどうすればよいですか? 現在 afterTraverse 関数を使用して配列を出力していますが、これは正しくないと思います

public function afterTraverse(array $nodes) {
        var_dump($this->variables);
    }

メインファイルでクラスを初期化し、$obj->array を使用してアクセスする必要がありますか?

4

0 に答える 0