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

> Discover how code-review-graph parses PHP Laravel code, adding framework-specific details like routes, models, and Blade templates to its analysis.

- Repository: [Tirth Kanani/code-review-graph](https://github.com/tirth8205/code-review-graph)
- Tags: internals
- Published: 2026-08-09

---

**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`](https://github.com/tirth8205/code-review-graph/blob/main/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`](https://github.com/tirth8205/code-review-graph/blob/main/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.

```python
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`](https://github.com/tirth8205/code-review-graph/blob/main/.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`](https://github.com/tirth8205/code-review-graph/blob/main/.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.

```python
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`](https://github.com/tirth8205/code-review-graph/blob/main/.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`](https://github.com/tirth8205/code-review-graph/blob/main/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`](https://github.com/tirth8205/code-review-graph/blob/main/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`](https://github.com/tirth8205/code-review-graph/blob/main/.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.