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(4mo ago)242[3 PRs](https://github.com/marcokoepfli/laravel-patrol/pulls)MITPHPPHP ^8.3CI passing

Since Mar 15Pushed 3mo 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 2d 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

40

—

FairBetter than 86% of packages

Maintenance77

Regular maintenance activity

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

148d 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.2k12.6M135](/packages/dedoc-scramble)[elegantly/laravel-translator

All on one translations management for Laravel

6339.5k](/packages/elegantly-laravel-translator)[psalm/plugin-laravel

Psalm plugin for Laravel

3345.4M354](/packages/psalm-plugin-laravel)[rawilk/profile-filament-plugin

Profile &amp; MFA starter kit for filament.

3915.5k](/packages/rawilk-profile-filament-plugin)[harris21/laravel-fuse

Circuit breaker for Laravel queue jobs. Protect your workers from cascading failures.

46273.9k](/packages/harris21-laravel-fuse)[vormkracht10/laravel-mails

Laravel Mails can collect everything you might want to track about the mails that has been sent by your Laravel app.

25060.1k](/packages/vormkracht10-laravel-mails)

PHPackages © 2026

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