# PHP/Laravel Framework Features Detected by Code-Review-Graph (CRG)

> Discover how Code-Review-Graph detects 8 Laravel features like Composer PSR-4 routing facades and Eloquent ORM transforming PHP code into a queryable knowledge graph. Learn more.

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

---

**CRG automatically extracts eight distinct Laravel framework features—including Composer PSR-4 resolution, Blade template inheritance, routing facades, and Eloquent ORM relationships—transforming raw PHP source into a queryable knowledge graph with explicit semantic edges.**

The `tirth8205/code-review-graph` repository extends its core PHP parser with deep Laravel awareness, enabling precise blast-radius analysis for PHP/Laravel projects. Unlike generic static analysis tools, CRG identifies framework-specific conventions ranging from Blade view references to Eloquent model relationships, allowing AI assistants to navigate large Laravel codebases through semantic edges rather than simple text search.

## Composer PSR-4 Autoloading Resolution

CRG maps class names to their physical files by implementing repository-bounded PSR-4 logic that respects the `autoload` and `autoload-dev` sections of [`composer.json`](https://github.com/tirth8205/code-review-graph/blob/main/composer.json). In [`code_review_graph/parser.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/parser.py), the `_resolve_module_to_file` method calls `_read_php_composer_psr4` to perform longest-prefix matching while safeguarding against path traversal and symlink escapes (lines 11050–11142). This ensures that `use App\Models\User` correctly resolves to the file defined in the PSR-4 mapping, even when multiple namespace prefixes overlap.

## Blade Template Engine Integration

When CRG encounters Blade syntax, it creates explicit `IMPORTS_FROM` edges linking templates to their dependencies. The parser treats files detected as the *blade* language in `CodeParser.parse_bytes`, emitting edges with `extra["framework"] == "laravel"` for directives including `@extends`, `@include`, `@component`, and `@livewire` (including their escaped forms). This captures the view inheritance chain that defines Laravel’s presentation layer, as validated in [`tests/test_php_laravel.py`](https://github.com/tirth8205/code-review-graph/blob/main/tests/test_php_laravel.py) (lines 4–24).

## Laravel Routing Facade Detection

CRG extracts routing calls such as `Route::get` or `Router::post` and produces `CALLS` edges annotated with `laravel_kind: "route"`, linking the route definition to its target controller method. However, the parser requires **static handler evidence**: the call must originate from a known facade import (`use Illuminate\Support\Facades\Route as Router`) or a fully-qualified `\Illuminate\Support\Facades\Route` reference. Without this import evidence, the call is treated as generic PHP. This logic is tested in `TestLaravelSemantics.test_laravel_requires_route_import_when_short_facade_is_used` and `test_laravel_route_alias_resolves_grouped_controller_import` (lines 27–48 and 58–73).

## Eloquent ORM Relationship Mapping

For models extending `Illuminate\Database\Eloquent\Model`, CRG recognizes relationship methods—including `hasMany`, `belongsTo`, `hasOne`, and `morphOne`—and creates `REFERENCES` edges with `extra["relationship"]` set to the exact relationship type. The parser first verifies that the class inherits from the Eloquent base class before emitting these edges, ensuring that only true models trigger relationship detection. This behavior is verified in `TestLaravelSemantics.test_laravel_eloquent_aliases_resolve_model_reference` and the inheritance test (lines 80–106 and 110–124).

## Defensive Parsing Safeguards

CRG implements namespace-block isolation to prevent `use` statements from leaking across different namespace blocks, eliminating false-positive Blade or Eloquent edges. This is confirmed by `TestLaravelSemantics.test_laravel_namespace_block_imports_do_not_leak` (lines 30–56). Additionally, when an Eloquent model cannot be resolved (e.g., the class is missing), CRG emits a stable short target containing the class name rather than dropping the edge entirely, as demonstrated in `test_laravel_unresolved_model_keeps_stable_short_target` (lines 122–136).

## Querying the Laravel Knowledge Graph

Once parsed, Laravel-specific edges can be queried via MCP tools to perform targeted codebase analysis.

Extract all route definitions:

```json
{
  "tool": "query_graph_tool",
  "args": {
    "pattern": "CALLS",
    "extra": { "framework": "laravel", "laravel_kind": "route" }
  }
}

```

Find all Blade view imports:

```json
{
  "tool": "query_graph_tool",
  "args": {
    "pattern": "IMPORTS_FROM",
    "extra": { "framework": "laravel" }
  }
}

```

List specific Eloquent relationships:

```json
{
  "tool": "query_graph_tool",
  "args": {
    "pattern": "REFERENCES",
    "extra": { "framework": "laravel", "relationship": "hasMany" }
  }
}

```

## Summary

- **Composer PSR-4 Resolution**: Maps class names to files using `_read_php_composer_psr4` with path traversal protection (`parser.py:11050–11142`).
- **Blade Template Detection**: Creates `IMPORTS_FROM` edges for `@extends`, `@include`, `@component`, and `@livewire` directives.
- **Routing Facade Extraction**: Generates `CALLS` edges with `laravel_kind: "route"` only when static handler evidence confirms Laravel facade usage.
- **Eloquent Relationship Edges**: Emits `REFERENCES` edges annotated with relationship types for classes extending `Illuminate\Database\Eloquent\Model`.
- **Namespace Isolation**: Prevents import leakage across namespace blocks to ensure accurate edge attribution.
- **Graceful Degradation**: Preserves unresolved model references as stable short targets rather than omitting edges.

## Frequently Asked Questions

### How does CRG handle unresolved Laravel models?

When CRG encounters an Eloquent relationship referencing a model that cannot be resolved to a file (e.g., the class is missing or autoloaded externally), it does not drop the edge. Instead, the parser emits a stable short target containing the class name, ensuring that the relationship is still represented in the graph for analysis. This behavior is validated in [`tests/test_php_laravel.py`](https://github.com/tirth8205/code-review-graph/blob/main/tests/test_php_laravel.py) lines 122–136.

### What prevents false-positive route detection in CRG?

CRG requires **static handler evidence** before treating a method call as a Laravel route. The parser verifies that the call originates from an imported facade (`use Illuminate\Support\Facades\Route`) or a fully-qualified namespace (`\Illuminate\Support\Facades\Route`). Without this import evidence, the call is classified as a generic PHP call, preventing non-framework code from generating spurious route edges.

### How does CRG map PSR-4 autoloaded classes to their files?

The parser reads the `autoload` and `autoload-dev` sections of [`composer.json`](https://github.com/tirth8205/code-review-graph/blob/main/composer.json) via `_read_php_composer_psr4`, then applies longest-prefix matching to resolve namespace segments to directory paths. Implemented in `CodeParser._resolve_module_to_file` (`parser.py:11050–11142`), this logic includes safeguards against path traversal and symlink escapes, ensuring that `use` statements resolve only to files within the repository boundary.

### Can CRG detect Livewire components within Blade templates?

Yes. CRG recognizes the `@livewire` directive (and its escaped variants) when parsing Blade files, creating `IMPORTS_FROM` edges with `extra["framework"] == "laravel"` pointing to the referenced Livewire component. This detection works alongside standard Blade directives like `@extends` and `@include`, providing complete coverage of Laravel’s templating layer as tested in [`tests/test_php_laravel.py`](https://github.com/tirth8205/code-review-graph/blob/main/tests/test_php_laravel.py) lines 4–24.