Code analyzer for extracting symbols, structure, and relationships from PHP files. Includes full support for the Laravel framework. Indexes code for semantic search in Qdrant.
The PHP analyzer parses .php files and extracts:
โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ
โ .php Files โโโโโโถโ PHP Analyzer โโโโโโถโ CodeChunks โ
โ (source code) โ โ (VKCOM parser) โ โ (structured) โ
โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโฌโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโโโโ โ
โ Laravel Analyzer โโโโโโโโโโโโโโโโค
โ (Eloquent, etc.) โ โ
โโโโโโโโโโโโโโโโโโโโ โผ
โโโโโโโโโโโโโโโโโโโ
โ Qdrant โ
โ (vector store) โ
โโโโโโโโโโโโโโโโโโโ
type: "class")<?php
namespace App\Models;
/**
* Represents a user in the system.
*/
class User extends Model implements Authenticatable
{
use SoftDeletes, Notifiable;
protected $fillable = ['name', 'email'];
protected $casts = ['email_verified_at' => 'datetime'];
}
Extracted information:
| Field | Value | Description |
|โโ-|โโ-|โโโโ-|
| name | "User" | Class name |
| namespace | "App\\Models" | Namespace |
| full_name | "App\\Models\\User" | Fully qualified name |
| extends | "Model" | Parent class |
| implements | ["Authenticatable"] | Implemented interfaces |
| traits | ["SoftDeletes", "Notifiable"] | Used traits |
| is_abstract | false | If abstract |
| is_final | false | If final |
| docstring | "Represents a user..." | PHPDoc |
type: "method")/**
* Returns the user's orders.
*
* @param int $limit Maximum number of orders
* @return Collection<Order>
*/
public function getOrders(int $limit = 10): Collection
{
return $this->orders()->limit($limit)->get();
}
Extracted information:
| Field | Value | Description |
|โโ-|โโ-|โโโโ-|
| name | "getOrders" | Method name |
| visibility | "public" | Visibility |
| is_static | false | If static |
| is_abstract | false | If abstract |
| parameters | [{name: "limit", type: "int", default: "10"}] | Parameters |
| return_type | "Collection" | Return type |
| phpdoc.params | [{name: "limit", type: "int", desc: "..."}] | PHPDoc params |
| phpdoc.return | {type: "Collection<Order>", desc: ""} | PHPDoc return |
type: "interface")interface PaymentGateway extends Gateway
{
public function charge(float $amount): bool;
public function refund(string $transactionId): bool;
}
type: "trait")trait Auditable
{
public function getCreatedBy(): ?User { ... }
public function logActivity(string $action): void { ... }
}
type: "function")/**
* Helper for price formatting.
*/
function format_price(float $amount, string $currency = 'USD'): string
{
return number_format($amount, 2) . ' ' . $currency;
}
class Order extends Model
{
protected $fillable = ['user_id', 'total', 'status'];
protected $casts = ['total' => 'decimal:2'];
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
public function items(): HasMany
{
return $this->hasMany(OrderItem::class);
}
public function scopeCompleted($query)
{
return $query->where('status', 'completed');
}
public function getTotalFormattedAttribute(): string
{
return number_format($this->total, 2) . ' USD';
}
}
Extracted Laravel metadata:
{
"is_eloquent_model": true,
"fillable": ["user_id", "total", "status"],
"casts": {"total": "decimal:2"},
"relations": [
{"name": "user", "type": "belongsTo", "related": "User"},
{"name": "items", "type": "hasMany", "related": "OrderItem"}
],
"scopes": ["completed"],
"accessors": ["total_formatted"]
}
class OrderController extends Controller
{
public function index(): View { ... }
public function store(OrderRequest $request): RedirectResponse { ... }
public function show(Order $order): View { ... }
}
Controller metadata:
{
"is_controller": true,
"is_resource_controller": true,
"actions": ["index", "store", "show"],
"http_methods": {
"index": "GET",
"store": "POST",
"show": "GET"
}
}
Route::get('/orders', [OrderController::class, 'index'])->name('orders.index');
Route::resource('users', UserController::class);
php/
โโโ types.go # PHP types: ClassInfo, MethodInfo, etc.
โโโ analyzer.go # PathAnalyzer implementation (21KB)
โโโ api_analyzer.go # APIAnalyzer for documentation
โโโ phpdoc.go # PHPDoc parser
โโโ analyzer_test.go # 10 CodeAnalyzer tests
โโโ api_analyzer_test.go # 4 APIAnalyzer tests
โโโ parser_test.go # 5 parser tests
โโโ README.md # This documentation
โโโ laravel/ # Laravel module
โโโ types.go # Laravel-specific types
โโโ analyzer.go # Laravel coordinator
โโโ adapter.go # PathAnalyzer adapter
โโโ eloquent.go # Eloquent Models analyzer
โโโ controller.go # Controllers analyzer
โโโ routes.go # Routes analyzer
โโโ README.md # Laravel documentation
import "github.com/doITmagic/rag-code-mcp/internal/ragcode/analyzers/php/laravel"
// For Laravel projects (recommended)
analyzer := laravel.NewAdapter()
// Analyze directories/files
chunks, err := analyzer.AnalyzePaths([]string{"./app"})
for _, chunk := range chunks {
fmt.Printf("[%s] %s\n", chunk.Type, chunk.Name)
if relations, ok := chunk.Metadata["relations"]; ok {
fmt.Printf(" Relations: %v\n", relations)
}
}
The PHP/Laravel analyzer is automatically selected for:
php - generic PHP projectslaravel - Laravel projectsphp-laravel - Laravel alternative| File/Directory | Project Type |
|---|---|
artisan |
Laravel |
composer.json |
PHP |
app/Models/ |
Laravel |
routes/web.php |
Laravel |
| Type | Description | Example |
|---|---|---|
class |
PHP class | class User extends Model |
method |
Class method | public function save() |
function |
Global function | function helper() |
interface |
Interface | interface Payable |
trait |
Trait | trait Auditable |
const |
Class constant | const STATUS_ACTIVE = 1 |
property |
Property | protected $fillable |
{
"namespace": "App\\Models",
"extends": "Model",
"implements": ["Authenticatable"],
"traits": ["SoftDeletes"],
"is_abstract": false,
"is_final": false,
"is_eloquent_model": true,
"fillable": ["name", "email"],
"relations": [...]
}
{
"class_name": "UserController",
"visibility": "public",
"is_static": false,
"is_abstract": false,
"is_final": false,
"parameters": [...],
"return_type": "View",
"phpdoc": {
"description": "...",
"params": [...],
"return": {...}
}
}
# All PHP tests (19 tests)
go test ./internal/ragcode/analyzers/php/...
# Laravel only (21 tests)
go test ./internal/ragcode/analyzers/php/laravel/...
# With coverage
go test -cover ./internal/ragcode/analyzers/php/...
Results:
| Limitation | Description |
|---|---|
| No Runtime | Static analysis, doesnโt execute code |
| Single-file | Each file is analyzed independently |
| No Autoload | Doesnโt resolve Composer autoload |
extends Model)$fillable, $guarded, $casts, $table, $primaryKeyhasOne, hasMany, belongsTo, belongsToMany, hasManyThrough, morphTo, morphMany, morphToMany, morphedByManyscopeMethodName() detectiongetXxxAttribute(), setXxxAttribute()extends Controller)routes/web.php, routes/api.php)Route::get(), Route::post(), etc.Route::match() supportRoute::resource() expansion[Controller::class, 'action']analyzer.go (21KB, 814 lines)api_analyzer.go (7.4KB, 293 lines)phpdoc.go (5.3KB, 217 lines)Follows the same pattern as golang analyzer with modular framework support:
php/
โโโ types.go - Internal type definitions
โโโ analyzer.go - PathAnalyzer implementation
โโโ api_analyzer.go - APIAnalyzer implementation
โโโ phpdoc.go - PHPDoc parser (PHP-specific helper)
โโโ analyzer_test.go - CodeAnalyzer tests
โโโ api_analyzer_test.go - APIAnalyzer tests
โโโ parser_test.go - Parser validation tests
โโโ laravel/ - Laravel framework module (separate package)
โโโ types.go - Laravel-specific types (Eloquent, Controllers, Routes)
โโโ analyzer.go - Laravel framework analyzer coordinator
โโโ eloquent.go - Eloquent Model analyzer
โโโ controller.go - Controller analyzer
โโโ README.md - Laravel module documentation
Framework-specific analyzers are separated into their own packages:
This modular design allows: