nikic/PHP-Parser: an AST for PHP, built in PHP
A PHP parser written in PHP
At a glance
- What is it?
- nikic/PHP-Parser turns PHP source into a traversable abstract syntax tree and prints it back as code. It is the foundation layer for static analysis, codemods and code generation, and it is meant for developers who write PHP tooling rather than for people who want to lint a file.
- Who is it for?
- Adopt nikic/PHP-Parser if you are building static analysis, a codemod, or code generation and need a PHP 7 and PHP 8 AST with location information and a printer that preserves formatting on untouched nodes. Do not adopt it if you only want to check one file by hand, or if you need to parse PHP 5.x reliably: the 5.x documentation describes that support as limited.
- Can I use it commercially?
- Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly PHP, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
What nikic/PHP-Parser is for, and who actually needs it
The README states the purpose plainly: the library exists "to simplify static code analysis and manipulation." That is a narrower audience than the name suggests. If you want to know whether a file is syntactically valid, PHP's own tokenizer and lint mode do that without a dependency. PHP-Parser is for the next step: you need a tree you can walk, inspect and rewrite, and you need to turn that tree back into source code afterwards.
Three kinds of projects fit. Static analysers that need to know what a name refers to, not just where it appears. Codemods that rename a method across a codebase or insert a type declaration, where the output must still look like the input everywhere you did not touch. Code generators that build PHP from a schema or a template and want a structured way to emit it. The library parses PHP 7.0 through PHP 8.4 on the 5.x line, with limited support for PHP 5.x, and it runs on PHP 7.4 or newer. The 4.x line is still supported and targets older runtimes, so the version you pick is a decision about your own deployment, not a preference.
How the parse, traverse and print pipeline works
The pipeline has three stages and the library gives you a component for each. The parser reads source text and returns an array of statement nodes, each carrying attributes such as start and end positions. The documentation advertises accurate location information, which is what lets a tool report an error at a line and column rather than at a file.
Traversal is where the design gets interesting. A NodeTraverser holds a list of visitors, and each visitor gets enterNode and leaveNode callbacks as the traverser descends and ascends. A visitor can return a node to replace the current one, return an array to splice in several, or return NodeTraverser::DONT_TRAVERSE_CHILDREN to stop the descent. The documentation also covers interleaved visitors and short-circuiting traversals, which matters when you want to stop walking as soon as a match is found.
Two supporting pieces do work that is easy to underestimate. Name resolution rewrites unqualified names into fully qualified ones according to PHP's namespace rules, so your visitor does not have to reimplement that logic. Constant expression evaluation resolves initializers such as constant and property defaults, and the docs note it handles errors and unsupported expressions rather than assuming every initializer is simple. Printing is the last stage: the standard pretty printer turns an AST back into code, and the documentation describes formatting-preserving transformations, where nodes you did not modify keep their original layout. That last feature is the difference between a codemod people accept and one they reject in review.
Installing nikic/PHP-Parser and dumping your first AST
Installation is a Composer require. The README gives the command as php composer.phar require nikic/php-parser; if composer is already on your PATH, the equivalent is composer require nikic/php-parser. This pulls the current 5.x release, which needs PHP 7.4 or newer on the machine doing the parsing.
The first real use is to parse a snippet and dump the tree. The README builds the parser through ParserFactory and calls createForNewestSupportedVersion, which selects the newest PHP grammar the library supports:
<?php
use PhpParser\Error;
use PhpParser\NodeDumper;
use PhpParser\ParserFactory;
$parser = (new ParserFactory())->createForNewestSupportedVersion();
try {
$ast = $parser->parse($code);
} catch (Error $error) {
echo "Parse error: {$error->getMessage()}\n";
}The NodeDumper output is human-readable and nested. For a function named test with one parameter and a var_dump call inside, the dump begins with Stmt_Function and lists attrGroups, byRef, name, params, returnType and stmts as fields. Reading that output is the fastest way to learn the node class names you will match against later.
Modification follows the same shape. The README shows a visitor that checks whether a node is an instance of PhpParser\Node\Stmt\Function_ and, if so, sets its stmts property to an empty array. Adding that visitor to a NodeTraverser and calling traverse returns a new tree with every function body removed.
$traverser = new NodeTraverser();
$traverser->addVisitor(new class extends NodeVisitorAbstract {
public function enterNode(Node $node) {
if ($node instanceof Function_) {
$node->stmts = [];
}
}
});
$ast = $traverser->traverse($ast);Printing closes the loop. A PrettyPrinter\Standard instance has prettyPrintFile, which takes the AST and returns source. In the README's example the result is the original file with the var_dump call gone and the function body empty.
Where PHP-Parser stops being the right tool
The library parses syntax. It does not type-check, does not resolve what a method call dispatches to at runtime, and does not build a call graph. If your question is "does this variable hold a string here", the AST alone will not answer it; you need a type inference layer on top, which is why tools in this space are built on PHP-Parser rather than being PHP-Parser.
Version coverage is the second boundary. The 5.x documentation lists PHP 7.0 to PHP 8.4 with limited support for parsing PHP 5.x. If your codebase still contains PHP 5 code, that word "limited" is doing real work, and the 4.x line covers PHP 5.2 through PHP 8.3 on PHP 7.0 and up. You cannot simply take the newest release and assume the oldest code parses.
Performance is the third. The documentation has a dedicated performance page whose listed topics are disabling Xdebug, reusing objects, and garbage collection impact. That list tells you what the maintainers consider the usual causes of slowness: a debugger attached, allocation churn, and GC pressure. Parsing a large codebase with Xdebug enabled is a known way to make the library look far slower than it is, and the fix is configuration, not code. There is also a separate grammar directory and a bin directory in the repository, which is worth knowing before you assume the lib directory is the whole project.
PHP-Parser against tree-sitter and PHP's own tokenizer
The obvious alternative for multi-language tooling is tree-sitter, which parses PHP with a generated C grammar and exposes a concrete syntax tree through bindings in many languages. The difference in approach is not speed alone. Tree-sitter is designed for editors: it does incremental reparsing and error recovery so a syntax tree stays usable while you type. PHP-Parser is designed for batch transformation: it produces PHP-specific node classes with typed properties, a name resolver that applies PHP's namespace rules, a constant expression evaluator, and a pretty printer that can emit code. Tree-sitter gives you a tree; PHP-Parser gives you a tree plus the machinery to understand and rewrite PHP specifically.
PHP's own token_get_all is the other comparison, and it is not really a competitor. It hands you a flat token stream with no nesting, so reconstructing scope and structure is your problem. For a quick check of whether a file parses, it is lighter. For anything that needs to reason about nesting, it is the wrong level of abstraction. If your tool is written in Python or Rust and you only need to find patterns, the related searches for a PHP parser in those languages point at bindings and ports rather than at this library, which is PHP-only by design.
Maintenance, licence and the real cost of a major version
The repository is not archived, and the last push was on 2026-09-14. Releases are frequent: v5.9.0 on 2026-09-13, v5.8.0 on 2026-07-04, v5.7.0 on 2025-12-06. For a library that must track PHP's own grammar as new language versions ship, that cadence is the maintenance signal that matters, because a parser that lags the language is useless for analysing modern code.
The licence is BSD-3-Clause, a permissive licence that allows use in closed-source products. That is a fact about the licence text, not advice about your situation; if you redistribute the library or a derivative, read the LICENSE file in the repository and handle the attribution clause as your own legal review requires.
The upgrade cost is the part teams underestimate. The repository ships UPGRADE-1.0.md through UPGRADE-5.0.md, one document per major version. Those files exist because the node API changes between majors, and a visitor written against 4.x will not necessarily compile against 5.x. The practical consequence is that pinning a major version in composer.json and reading the matching UPGRADE file before moving is cheaper than discovering the changes through a broken build. Note also that the 5.x line requires PHP 7.4 on the host, so a tool that must run on PHP 7.0 to 7.3 has to stay on 4.x even if it parses 8.x code.
Editorial conclusion
Adopt nikic/PHP-Parser if you are building static analysis, a codemod, or code generation and need a PHP 7 and PHP 8 AST with location information and a printer that preserves formatting on untouched nodes. Do not adopt it if you only want to check one file by hand, or if you need to parse PHP 5.x reliably: the 5.x documentation describes that support as limited. Before committing, check the UPGRADE-5.0.md file for the API changes between major versions, and confirm which PHP version your target code must parse, because 4.x and 5.x support different ranges.
Frequently asked questions
What is nikic/PHP-Parser?
It is a PHP parser written in PHP whose stated purpose is to simplify static code analysis and manipulation. It parses PHP 7 and PHP 8 code into an abstract syntax tree, and the same library can dump that tree, traverse and modify it, and print it back to PHP code.
How do I install nikic/PHP-Parser?
Install it with Composer. The README gives the command as php composer.phar require nikic/php-parser, and the 5.x line requires PHP 7.4 or newer on the machine running the parser.
Can I run nikic/PHP-Parser on npm or in Python or Rust?
No. The library is written in PHP and installed through Composer, and the repository is a PHP package. A project in another language would need a separate parser or a binding rather than this library.
Which PHP versions can nikic/PHP-Parser parse?
The 5.x documentation covers parsing PHP 7.0 to PHP 8.4, with limited support for parsing PHP 5.x. The 4.x documentation is still supported and covers parsing PHP 5.2 to PHP 8.3, running on PHP 7.0 and up.
Why is nikic/PHP-Parser slow for me?
The documentation has a performance page whose listed topics are disabling Xdebug, reusing objects and garbage collection impact. That points at a debugger being attached and at allocation churn as the usual causes rather than at the parser itself.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/nikic-php-parser)
Community notes