# PHPStan

**Package:** Laravel Modules | **Version:** 3 | **URL:** https://mozex.dev/docs/laravel-modules/v3/integrations/phpstan

---

PHPStan needs to know about your module directories to analyse them. The trick is using a PHP config file (`phpstan.php`) instead of the NEON format, which lets you `glob()` module directories at runtime. New modules are picked up automatically without editing the config.

## Configuration

Create a `phpstan.php` file at your project root:

```php
<?php

return [
    'includes' => [
        './vendor/larastan/larastan/extension.neon',
    ],
    'parameters' => [
        'level' => 5,
        'paths' => [
            __DIR__ . '/app',
            __DIR__ . '/config',
            ...glob(__DIR__ . '/Modules/*', GLOB_ONLYDIR),
        ],
        'excludePaths' => [
            'analyseAndScan' => [
                ...glob(__DIR__ . '/Modules/*/Tests', GLOB_ONLYDIR),
                ...glob(__DIR__ . '/Modules/*/Database', GLOB_ONLYDIR),
                ...glob(__DIR__ . '/Modules/*/Resources', GLOB_ONLYDIR),
            ],
        ],
        'databaseMigrationsPath' => glob('Modules/*/Database/Migrations', GLOB_ONLYDIR),
        'tmpDir' => 'storage/phpstan',
        'checkOctaneCompatibility' => true,
        'checkModelProperties' => true,
    ],
];
```

### What each section does

**`paths`**: Uses `...glob()` (the spread operator, PHP 8.1+) to include every module directory. When you add a new module, it's automatically included in the next analysis.

**`excludePaths`**: Skips directories that shouldn't be analysed: test files, database seeders/migrations/factories, and Blade views. These either have their own analysis tools or contain code that PHPStan can't usefully check.

**`databaseMigrationsPath`**: Tells Larastan where to find migration files. This is how PHPStan knows about your database schema when checking model property access. Without this, it can't verify `$post->title` against the actual columns.

## Running PHPStan

Since the config file isn't named `phpstan.neon`, you have to pass `-c phpstan.php` on every invocation. That gets tedious fast. Add a couple of composer scripts so you can forget about the flag entirely:

```json
{
    "scripts": {
        "test:types": "phpstan analyse -c phpstan.php --memory-limit=-1 --ansi",
        "baseline": "@test:types --allow-empty-baseline --generate-baseline phpstan-baseline.php"
    }
}
```

Now you run:

```bash
composer test:types
```

To analyse a single module, pass the path through the script:

```bash
composer test:types -- Modules/Blog
```

## Baselines

If you're adding PHPStan to a project with existing modules, generate a baseline to suppress current issues and work from a clean slate. With the composer scripts above in place:

```bash
composer baseline
```

This runs `test:types` with the baseline flags appended, writing all current errors to `phpstan-baseline.php`.

Once the file exists, register it in the `includes` array of your `phpstan.php` so PHPStan actually applies it on the next run:

```php
return [
    'includes' => [
        './vendor/larastan/larastan/extension.neon',
        './phpstan-baseline.php',
    ],
    // ...
];
```

Only add this line after `phpstan-baseline.php` has been generated. Including a file that doesn't exist yet causes PHPStan to fail at startup, which creates a chicken-and-egg problem (you can't run PHPStan to generate the baseline because PHPStan won't start without the baseline).

With the baseline in place, new code gets checked at the configured level while existing issues stay suppressed in the baseline file. Fix them gradually and regenerate the baseline with `composer baseline` whenever you want to shrink the suppressed set.

## Custom modules directory

If you've changed `modules_directory` in the package config, update the glob patterns to match:

```php
// If modules live in src/Domains/
...glob(__DIR__ . '/src/Domains/*', GLOB_ONLYDIR),
```

---

## Table of Contents

- [Introduction](https://mozex.dev/docs/laravel-modules/v3)
- [AI Integration](https://mozex.dev/docs/laravel-modules/v3/ai-integration)
- [Support Us](https://mozex.dev/docs/laravel-modules/v3/support-us)
- [Requirements](https://mozex.dev/docs/laravel-modules/v3/requirements)
- [Changelog](https://mozex.dev/docs/laravel-modules/v3/changelog)
- [Contributing](https://mozex.dev/docs/laravel-modules/v3/contributing)
- [Questions & Issues](https://mozex.dev/docs/laravel-modules/v3/questions-and-issues)
- [About Mozex](https://mozex.dev/docs/laravel-modules/v3/about)

### Features

- [Blade Components](https://mozex.dev/docs/laravel-modules/v3/features/blade-components)
- [Views](https://mozex.dev/docs/laravel-modules/v3/features/views)
- [Routes](https://mozex.dev/docs/laravel-modules/v3/features/routes)
- [Configs](https://mozex.dev/docs/laravel-modules/v3/features/configs)
- [Migrations](https://mozex.dev/docs/laravel-modules/v3/features/migrations)
- [Seeders](https://mozex.dev/docs/laravel-modules/v3/features/seeders)
- [Commands](https://mozex.dev/docs/laravel-modules/v3/features/commands)
- [Helpers](https://mozex.dev/docs/laravel-modules/v3/features/helpers)
- [Models & Factories](https://mozex.dev/docs/laravel-modules/v3/features/models-factories)
- [Policies](https://mozex.dev/docs/laravel-modules/v3/features/policies)
- [Events & Listeners](https://mozex.dev/docs/laravel-modules/v3/features/events-listeners)
- [Service Providers](https://mozex.dev/docs/laravel-modules/v3/features/service-providers)
- [Translations](https://mozex.dev/docs/laravel-modules/v3/features/translations)
- [Caching](https://mozex.dev/docs/laravel-modules/v3/features/caching)
- [Listing Modules](https://mozex.dev/docs/laravel-modules/v3/features/listing)
- [Livewire Components](https://mozex.dev/docs/laravel-modules/v3/features/livewire-components)
- [Filament](https://mozex.dev/docs/laravel-modules/v3/features/filament)
- [Nova Resources](https://mozex.dev/docs/laravel-modules/v3/features/nova-resources)

### Integrations

- [PHPStan](https://mozex.dev/docs/laravel-modules/v3/integrations/phpstan)
- [PHPUnit](https://mozex.dev/docs/laravel-modules/v3/integrations/phpunit)
- [Pest](https://mozex.dev/docs/laravel-modules/v3/integrations/pest)
- [Inertia](https://mozex.dev/docs/laravel-modules/v3/integrations/inertia)