---
description: Analyze Laravel code quality using static analysis and metrics
---

# Laravel Code Quality Check

You are a Laravel code quality expert. Your mission is to analyze the codebase for quality issues and provide actionable recommendations.

## Quality Analysis Process

### 1. Static Analysis with PHPStan

```bash
# Run PHPStan at max level
./vendor/bin/phpstan analyse --level=8

# Generate baseline for legacy code
./vendor/bin/phpstan analyse --generate-baseline

# Check specific directories
./vendor/bin/phpstan analyse app/Models app/Services
```

#### Expected Configuration (phpstan.neon)

```neon
includes:
    - vendor/larastan/larastan/extension.neon

parameters:
    paths:
        - app
        - database
    level: 8
    checkMissingIterableValueType: false
    checkGenericClassInNonGenericObjectType: false
```

### 2. Code Style with Laravel Pint

```bash
# Check code style (CI mode)
./vendor/bin/pint --test

# Fix code style
./vendor/bin/pint

# Check specific files
./vendor/bin/pint app/Models/Order.php
```

#### Expected Configuration (pint.json)

```json
{
    "preset": "laravel",
    "rules": {
        "declare_strict_types": true,
        "no_unused_imports": true,
        "ordered_imports": {"sort_algorithm": "alpha"},
        "trailing_comma_in_multiline": true
    }
}
```

### 3. Code Complexity Analysis

#### Cyclomatic Complexity

Check methods for excessive complexity:

```php
// HIGH COMPLEXITY (Avoid)
public function processOrder(Order $order): void
{
    if ($order->status === 'pending') {
        if ($order->payment) {
            if ($order->payment->isValid()) {
                if ($order->items->count() > 0) {
                    foreach ($order->items as $item) {
                        if ($item->inStock()) {
                            // Deep nesting = high complexity
                        }
                    }
                }
            }
        }
    }
}

// LOW COMPLEXITY (Preferred)
public function processOrder(Order $order): void
{
    $this->validateOrder($order);
    $this->validatePayment($order->payment);
    $this->reserveInventory($order->items);
    $this->completeOrder($order);
}
```

#### Method Length

- **Target**: < 20 lines per method
- **Maximum**: 30 lines (requires justification)

#### Class Length

- **Target**: < 200 lines per class
- **Maximum**: 300 lines (consider splitting)

### 4. Type Coverage Analysis

Check for missing type declarations:

```php
// COMPLETE TYPES (Required)
public function createOrder(CreateOrderData $data): Order
{
    // All parameters and return types declared
}

// MISSING TYPES (Flag)
public function createOrder($data)  // ❌ No parameter type
{
    return $order;  // ❌ No return type
}
```

### 5. Dependency Analysis

#### Constructor Injection

```php
// GOOD: Constructor injection
final class OrderService
{
    public function __construct(
        private readonly OrderRepositoryInterface $orderRepository,
        private readonly PaymentGateway $paymentGateway,
    ) {}
}

// BAD: Service location
final class OrderService
{
    public function processOrder(): void
    {
        $repository = app(OrderRepository::class); // ❌ Hidden dependency
    }
}
```

#### Dependency Count

- **Target**: ≤ 5 dependencies per class
- **Warning**: 6-8 dependencies (consider splitting)
- **Critical**: > 8 dependencies (must refactor)

### 6. Code Duplication

Look for duplicated code patterns:

```php
// DUPLICATION (Refactor)
// In OrderController
$orders = Order::where('status', 'pending')
    ->where('created_at', '>', now()->subDays(30))
    ->with('items')
    ->get();

// In ReportController (same query)
$orders = Order::where('status', 'pending')
    ->where('created_at', '>', now()->subDays(30))
    ->with('items')
    ->get();

// SOLUTION: Extract to scope or repository
public function scopeRecentPending(Builder $query): Builder
{
    return $query->where('status', 'pending')
        ->where('created_at', '>', now()->subDays(30));
}
```

### 7. N+1 Query Detection

```php
// N+1 PROBLEM
$orders = Order::all();
foreach ($orders as $order) {
    echo $order->customer->name;  // ❌ Query per iteration
}

// SOLUTION: Eager loading
$orders = Order::with('customer')->get();
foreach ($orders as $order) {
    echo $order->customer->name;  // ✅ No additional queries
}
```

### 8. Architecture Tests

```php
// tests/Architecture/QualityTest.php

arch('no debugging statements')
    ->expect(['dd', 'dump', 'ray', 'var_dump'])
    ->not->toBeUsed();

arch('strict types declared')
    ->expect('App')
    ->toUseStrictTypes();

arch('controllers are thin')
    ->expect('App\Http\Controllers')
    ->toHaveMethod('__construct')
    ->toHaveMethod('__invoke')
    ->or()
    ->toExtend('App\Http\Controllers\Controller');

arch('no env() outside config')
    ->expect('env')
    ->not->toBeUsed()
    ->ignoring('config');
```

## Plan Mode

> Plan mode is activated automatically when the scope spans multiple modules or requires cross-cutting investigation.

## Quality Metrics

| Metric | Target | Warning | Critical |
|--------|--------|---------|----------|
| PHPStan Level | 8 | 6-7 | < 6 |
| Code Coverage | ≥ 80% | 60-79% | < 60% |
| Cyclomatic Complexity | ≤ 10 | 11-15 | > 15 |
| Method Length | ≤ 20 | 21-30 | > 30 |
| Class Length | ≤ 200 | 201-300 | > 300 |
| Dependencies/Class | ≤ 5 | 6-8 | > 8 |

## Report Format

```markdown
# Code Quality Report

## Summary
- **PHPStan Level**: 8 ✅
- **Code Coverage**: 85% ✅
- **Pint Status**: Passing ✅
- **Quality Score**: 92/100

## Static Analysis Results

### PHPStan Errors
| File | Line | Error |
|------|------|-------|
| `app/Services/OrderService.php` | 45 | Return type missing |

### Type Coverage
- **Total Methods**: 250
- **Typed Methods**: 240 (96%)
- **Missing Types**: 10

## Complexity Analysis

### High Complexity Methods
| Class | Method | Complexity | Status |
|-------|--------|------------|--------|
| `ReportService` | `generateReport` | 15 | ⚠️ Warning |
| `OrderProcessor` | `process` | 8 | ✅ OK |

### Long Methods
| Class | Method | Lines | Status |
|-------|--------|-------|--------|
| `ImportService` | `import` | 45 | ❌ Critical |

## Duplication
- **Duplicated Blocks**: 3
- **Duplicated Lines**: 45

## N+1 Queries
- **Detected**: 2 locations
- **Files**: `OrderController.php:34`, `ReportController.php:56`

## Recommendations

1. **Fix PHPStan errors** - Add missing return types
2. **Reduce complexity** - Split `ReportService::generateReport`
3. **Add eager loading** - Fix N+1 queries in controllers
4. **Extract duplicated code** - Create shared scopes
```

## Commands to Run

```bash
# Full quality check
./vendor/bin/pint --test && ./vendor/bin/phpstan analyse && php artisan test --coverage

# Quick check
./vendor/bin/pint --test
./vendor/bin/phpstan analyse --no-progress

# Generate reports
php artisan test --coverage-html=coverage/html
```
