PHPackages                             marcokoepfli/laravel-patrol - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Testing &amp; Quality](/categories/testing)
4. /
5. marcokoepfli/laravel-patrol

ActiveLibrary[Testing &amp; Quality](/categories/testing)

marcokoepfli/laravel-patrol
===========================

An opinionated linter that patrols your Laravel app for convention violations

v1.0.1(3mo ago)237[3 PRs](https://github.com/marcokoepfli/laravel-patrol/pulls)MITPHPPHP ^8.3CI passing

Since Mar 15Pushed 2mo agoCompare

[ Source](https://github.com/marcokoepfli/laravel-patrol)[ Packagist](https://packagist.org/packages/marcokoepfli/laravel-patrol)[ Docs](https://github.com/marcokoepfli/laravel-patrol)[ GitHub Sponsors](https://github.com/marcokoepfli)[ RSS](/packages/marcokoepfli-laravel-patrol/feed)WikiDiscussions main Synced 3w ago

READMEChangelog (2)Dependencies (14)Versions (6)Used By (0)

 [![Laravel Patrol](art/logo.svg)](art/logo.svg)

 [![Latest Version on Packagist](https://camo.githubusercontent.com/4c0e27059eefa064580bb3a01599e4a28b719deada8019966c0fe7741923e94c/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6d6172636f6b6f6570666c692f6c61726176656c2d706174726f6c2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/marcokoepfli/laravel-patrol) [![Tests](https://camo.githubusercontent.com/ddd49a8d112c72bbb1b08ebfc4c8fee5a03e30dae7becff3b37218f1f52e763b/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6d6172636f6b6f6570666c692f6c61726176656c2d706174726f6c2f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/marcokoepfli/laravel-patrol/actions?query=workflow%3Arun-tests+branch%3Amain) [![PHPStan](https://camo.githubusercontent.com/2f8571ee0acbea21deacee6c9b84ccdb91848e598e29f0f19517824c27bc049b/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6d6172636f6b6f6570666c692f6c61726176656c2d706174726f6c2f7068707374616e2e796d6c3f6272616e63683d6d61696e266c6162656c3d7068707374616e267374796c653d666c61742d737175617265)](https://github.com/marcokoepfli/laravel-patrol/actions?query=workflow%3APHPStan+branch%3Amain) [![Total Downloads](https://camo.githubusercontent.com/b88610309e0c125da6e84a5e4877170d8a9dedd94155fd6cb728c387acff6216/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6d6172636f6b6f6570666c692f6c61726176656c2d706174726f6c2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/marcokoepfli/laravel-patrol)

An opinionated linter that patrols your Laravel app for convention violations. It checks if your code follows "the Laravel way" based on official Laravel documentation and provides actionable improvement suggestions with links to the relevant docs.

Why Patrol?
-----------

[](#why-patrol)

Tools like Larastan catch type errors. Pint fixes code style. **Patrol checks if you're actually using Laravel the way it was designed** — Form Requests instead of inline validation, config() instead of env(), Eloquent instead of raw queries, and more.

Every violation includes:

- A clear message explaining what's wrong
- A suggestion for how to fix it
- A link to the relevant Laravel docs section

Installation
------------

[](#installation)

```
composer require --dev marcokoepfli/laravel-patrol
```

Optionally publish the config:

```
php artisan vendor:publish --tag="patrol-config"
```

Usage
-----

[](#usage)

```
php artisan patrol
```

Example output:

```
  ██████╗  █████╗ ████████╗██████╗  ██████╗ ██╗
  ██╔══██╗██╔══██╗╚══██╔══╝██╔══██╗██╔═══██╗██║
  ██████╔╝███████║   ██║   ██████╔╝██║   ██║██║
  ██╔═══╝ ██╔══██║   ██║   ██╔══██╗██║   ██║██║
  ██║     ██║  ██║   ██║   ██║  ██║╚██████╔╝███████╗
  ╚═╝     ╚═╝  ╚═╝   ╚═╝   ╚═╝  ╚═╝ ╚═════╝ ╚══════╝

  v1.0 · Laravel 12 · 4 rules · the Laravel way

  app/Http/Controllers/UserController.php ....................................
  [WARNING] env() called outside of config files:11
           Move this env() call to a config file and use config() to retrieve the value.
           Docs: https://laravel.com/docs/12.x/configuration#accessing-configuration-values
  [WARNING] Inline validation: $request->validate():12
           Extract validation to a Form Request class using: php artisan make:request
           Docs: https://laravel.com/docs/12.x/validation#form-request-validation

  app/Services/ReportService.php .............................................
  [WARNING] env() called outside of config files:11
           Move this env() call to a config file and use config() to retrieve the value.
           Docs: https://laravel.com/docs/12.x/configuration#accessing-configuration-values
  [INFO] Raw database query: DB::select():12
         Consider using Eloquent models and relationships instead of raw queries.
         Docs: https://laravel.com/docs/12.x/eloquent

  Found 4 violation(s): 3 warning(s), 1 info

```

### Options

[](#options)

```
# Show everything including info-level hints
php artisan patrol --severity=info

# Run a specific rule only
php artisan patrol --rule=no-env-outside-config

# JSON output for CI pipelines
php artisan patrol --format=json
```

Configuration
-------------

[](#configuration)

```
// config/patrol.php
return [
    'version' => 12,           // Your Laravel version (11, 12)
    'preset' => 'recommended', // 'strict', 'recommended', 'relaxed'
    'rules' => [],             // Override individual rules (FQCN => bool)
    'paths' => ['app', 'routes', 'config', 'resources'],
    'exclude' => ['vendor', 'node_modules', 'storage'],
    'custom_rules' => [],      // Your own rule classes
];
```

### Presets

[](#presets)

PresetRulesUse case`relaxed`1 ruleJust the essentials`recommended`4 rulesSensible defaults for most projects`strict`6 rulesFull enforcement### Disabling a rule

[](#disabling-a-rule)

```
'rules' => [
    \MarcoKoepfli\LaravelPatrol\Rules\NoRawQueries::class => false,
],
```

Built-in Rules
--------------

[](#built-in-rules)

RuleIDSeverityDescriptionNoEnvOutsideConfig`no-env-outside-config`Warning`env()` should only be used in config filesUseFormRequests`use-form-requests`WarningUse Form Request classes instead of inline validationNoRawQueries`no-raw-queries`InfoPrefer Eloquent over raw DB queriesUseResourceControllers`use-resource-controllers`WarningUse `Route::resource()` for CRUD routesUseBladeComponents`use-blade-components`InfoPrefer Blade components over `@include`NoBusinessLogicInControllers`no-business-logic-in-controllers`WarningKeep controllers thin (max 10 statements per method)All PHP rules use AST parsing via [nikic/php-parser](https://github.com/nikic/PHP-Parser) — no regex matching. This means:

- `env()` in strings or comments is **not** flagged
- `$service->validate()` is **not** confused with `$request->validate()`
- `DB::table()` and `DB::transaction()` are correctly ignored by the raw query rule

Suppressing violations
----------------------

[](#suppressing-violations)

Add `@patrol-ignore` on the line above or the same line:

```
// @patrol-ignore
$key = env('APP_KEY');
```

```
{{-- @patrol-ignore --}}
@include('partials.legacy')
```

Custom Rules
------------

[](#custom-rules)

Create a class extending `AbstractRule`:

```
use MarcoKoepfli\LaravelPatrol\Enums\LaravelVersion;
use MarcoKoepfli\LaravelPatrol\ProjectContext;
use MarcoKoepfli\LaravelPatrol\Rules\AbstractRule;

class NoTodoComments extends AbstractRule
{
    public function id(): string
    {
        return 'no-todo-comments';
    }

    public function description(): string
    {
        return 'TODO comments should be resolved before merging.';
    }

    public function docsUrl(LaravelVersion $version): string
    {
        return 'https://your-team-wiki.com/conventions';
    }

    public function check(ProjectContext $context): array
    {
        $violations = [];

        foreach ($context->phpFiles() as $file) {
            // Use $context->analyzer() for AST parsing
            // Use $this->violation() to create results
            // Use $this->shouldIgnore() for @patrol-ignore support
        }

        return $violations;
    }
}
```

Register in `config/patrol.php`:

```
'custom_rules' => [
    \App\Patrol\NoTodoComments::class,
],
```

Testing
-------

[](#testing)

```
composer test       # Run tests
composer analyse    # Run PHPStan
composer format     # Fix code style
```

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](CONTRIBUTING.md) for details.

Credits
-------

[](#credits)

- [Marco Koepfli](https://github.com/marcokoepfli)
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

41

—

FairBetter than 87% of packages

Maintenance84

Actively maintained with recent releases

Popularity12

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity53

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

2

Last Release

103d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/d6259f131eae68de6e347349c1a1e6a9fbdf9a9e2dcb5470e75b0a9d5eceff6b?d=identicon)[marcokoepfli](/maintainers/marcokoepfli)

---

Top Contributors

[![marcokoepfli](https://avatars.githubusercontent.com/u/120577657?v=4)](https://github.com/marcokoepfli "marcokoepfli (8 commits)")

---

Tags

laravellinterBest-Practicesconventionspatrol

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/marcokoepfli-laravel-patrol/health.svg)

```
[![Health](https://phpackages.com/badges/marcokoepfli-laravel-patrol/health.svg)](https://phpackages.com/packages/marcokoepfli-laravel-patrol)
```

###  Alternatives

[dedoc/scramble

Automatic generation of API documentation for Laravel applications.

2.1k9.9M90](/packages/dedoc-scramble)[psalm/plugin-laravel

Psalm plugin for Laravel

3345.1M337](/packages/psalm-plugin-laravel)[elegantly/laravel-translator

All on one translations management for Laravel

6326.3k](/packages/elegantly-laravel-translator)[spatie/laravel-pdf

Create PDFs in Laravel apps

1.0k4.3M42](/packages/spatie-laravel-pdf)[phparkitect/phparkitect

Enforce architectural constraints in your PHP applications

9184.1M24](/packages/phparkitect-phparkitect)[spatie/laravel-health

Monitor the health of a Laravel application

87411.3M153](/packages/spatie-laravel-health)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
