How code-review-graph Handles PHP Laravel Framework-Specific Parsing

code-review-graph treats PHP as a first-class language and adds a dedicated Laravel extension that enriches the graph with framework-specific relationships including routes, Eloquent models, and Blade templates.

The code-review-graph repository provides advanced static analysis capabilities for multiple languages, with particular sophistication in PHP Laravel framework-specific parsing. By combining Tree-sitter AST traversal with Composer autoloading semantics, the parser constructs a detailed knowledge graph that captures both standard PHP imports and Laravel-specific architectural patterns. This deep integration allows the tool to map controller methods to routes and model relationships with high fidelity.

Core PHP Parsing Infrastructure

The foundation of PHP support resides in the CodeParser class within code_review_graph/parser.py. This implementation uses a Tree-sitter grammar registered under the "php" key to generate an abstract syntax tree for every .php file encountered.

Composer PSR-4 Autoloading Resolution

To handle PHP's module system, the parser implements Composer-aware resolution. The _read_php_composer_psr4 function (defined at line 551) reads a repository's composer.json and extracts the autoload and autoload-dev PSR-4 mappings. This map is cached and subsequently used by _resolve_php_composer_module (line 12684) to translate fully-qualified class names into concrete file system paths.

from code_review_graph.parser import CodeParser

parser = CodeParser(repo_path)  # repo_path points to a Laravel project

edges = parser.parse_file(repo_path / "app/Models/User.php")

# edges now contain an IMPORTS_FROM edge for any `use` statements

Namespace and Import Extraction

The parser captures file-level context through _php_namespace_name (line 10549), which extracts the declared namespace. For import resolution, _php_import_bindings (line 10558) builds a map from short names to fully-qualified names by analyzing use statements. When resolving class references, _php_resolve_class_reference (line 10616) handles imported aliases and namespace prefixes to determine the canonical class name.

Laravel-Specific Graph Enrichment

Beyond generic PHP analysis, the system activates Laravel-specific extraction when it detects .blade.php files or Laravel framework constructs in the AST. The entry point _extract_php_laravel_edges (line 10403) orchestrates this process by delegating to specialized walkers.

Blade Template Detection

Files ending with .blade.php are recognized as Laravel view templates and processed through the same pipeline. This ensures that view-layer dependencies are captured alongside backend logic.

Route and Controller Mapping

The parser identifies route definitions through _php_route_handler (line 10667), which processes Route::get, Route::post, and similar static calls. These generate CALLS edges connecting the route definition node to the target controller method. The helper _php_laravel_caller (line 10767) resolves Laravel-specific method invocations, while _walk_php_laravel_sequence (line 10410) traverses statement sequences to locate route definitions and controller method calls.

parser = CodeParser(repo_path)
edges = parser.parse_file(repo_path / "routes/web.php")

# The graph will include CALLS edges such as:

#   Route::get('/users', 'UserController@index')

#   → edge from route definition to UserController::index method

Eloquent Model Relationship Mapping

For model analysis, _php_class_extends_eloquent_model (line 10637) identifies classes extending Eloquent models and extracts relationship methods like hasMany and belongsTo. These generate HAS_ONE or HAS_MANY edges connecting the source model to related model classes, enabling the graph to represent database relationship semantics.

Safety Mechanisms and Repository Boundaries

When resolving Composer mappings, the parser enforces strict repository boundaries through _php_repository_boundary (line 13084). This function discards mappings that point outside the repository root and ignores symlinked or absolute paths that would escape the project directory, preventing false positives and security issues.

End-to-End Integration Flow

When CodeParser.parse_file or parse_bytes processes a PHP file, the system executes a three-phase pipeline:

  1. Tree-sitter Parsing: The file is parsed into an AST using the PHP grammar.
  2. Generic PHP Walk: The parser extracts namespaces, imports, class references, and standard function calls.
  3. Laravel Enrichment: If the file ends with .blade.php or contains Laravel-specific constructs, _extract_php_laravel_edges is invoked to add framework-level semantics to the graph.

All extracted relationships ultimately feed into self._add_edge, producing a unified knowledge graph containing IMPORTS_FROM edges for standard PHP dependencies and Laravel-specific edges for routes and models.

Summary

  • Composer Integration: The parser reads composer.json PSR-4 mappings via _read_php_composer_psr4 (line 551) to resolve class names to file paths.
  • Import Resolution: Functions like _php_import_bindings (line 10558) and _php_resolve_class_reference (line 10616) handle PHP namespace aliases and fully-qualified name resolution.
  • Laravel Extensions: The _extract_php_laravel_edges (line 10403) pipeline processes Blade templates, routes, and Eloquent relationships.
  • Edge Types: The system generates IMPORTS_FROM, CALLS, and HAS_ONE/HAS_MANY edges to represent PHP and Laravel semantics.
  • Safety: _php_repository_boundary (line 13084) prevents path traversal outside the repository root.

Frequently Asked Questions

How does code-review-graph resolve PHP classes when Composer is not available?

The parser relies primarily on Composer's PSR-4 autoloading map via _read_php_composer_psr4. Without a composer.json, resolution falls back to basic namespace-to-directory heuristics, though accuracy decreases for projects using complex autoloading strategies.

What specific Laravel relationship types does the parser detect?

According to the source code in _php_class_extends_eloquent_model (line 10637), the parser identifies Eloquent relationship methods including hasMany, belongsTo, hasOne, and similar variants, creating corresponding HAS_MANY or HAS_ONE edges in the knowledge graph.

Can code-review-graph analyze Laravel packages located outside the main repository?

No. The _php_repository_boundary check (line 13084) explicitly discards mappings and file paths that resolve outside the repository root. This security measure prevents the parser from following symlinks or absolute paths that escape the project boundary.

How are Blade templates differentiated from standard PHP files?

The parser checks file extensions within _extract_php_laravel_edges (line 10403). Files ending with .blade.php trigger Laravel-specific analysis, while standard .php files undergo generic PHP parsing unless they contain Laravel-specific AST patterns such as Route:: static calls.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →