> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Statische Analyse für Pakete (PHPStan / Larastan)

> Einrichtung, Konfiguration, Typannotationen und CI-Automatisierung mit PHPStan und Larastan, um Typsicherheit und Wartbarkeit von Laravel-Paketen zu verbessern.

Ein Laravel-Paket ist mit dem Release nicht abgeschlossen. Wer über Jahre hinweg mit Laravel-, PHP- und Abhängigkeits-Updates Schritt hält, sollte neben Tests auch die statische Analyse kontinuierlich betreiben.

<Info>
  Diese Seite ergänzt [Laravel-Paketentwicklung](/de/advanced/package-development), [Laravel-Pakete mit Orchestra Testbench testen](/de/advanced/package-testing) und [Versionskompatibilität von Paketen verwalten](/de/advanced/package-versioning). Ergänzen Sie Implementierung, Test und Versionsstrategie um statische Analyse, um Pakete langfristig wartbar zu halten.
</Info>

## Was ist statische Analyse?

Statische Analyse erkennt Typfehler und potenzielle Bugs, ohne den Code auszuführen. Da Laravel-Pakete viele dynamische Mechanismen wie Service Container, Facades und Eloquent nutzen, kann sie Probleme erkennen, die im reinen Betrieb leicht übersehen werden.

Die Einführung statischer Analyse bringt insbesondere:

* **Höhere Typsicherheit** — falsche Argumente oder Rückgabetypen fallen vor dem Review auf.
* **Frühe Fehlererkennung** — Aufrufe nicht existierender Methoden oder übersehene `null` werden vor Tests erkannt.
* **Bessere IDE-Vervollständigung** — saubere PHPDocs und Generics erhöhen die Präzision.
* **Stabilität in der Langzeitpflege** — nach Laravel-/PHP-Upgrades sind kaputte Stellen leichter zu finden.

## PHPStan einrichten

Bauen Sie zunächst die Basis mit PHPStan alleine auf. PHPStan 2.x geht strenger mit `mixed` und nullable um — Anlass, die Public API zu ordnen.

<Steps>
  <Step title="PHPStan als Dev-Abhängigkeit hinzufügen">
    ```bash theme={null}
    composer require --dev phpstan/phpstan:^2.0
    ```
  </Step>

  <Step title="Zunächst direkt Verzeichnisse analysieren">
    In Paketen sind meist `src` und `tests` die ersten Ziele.

    ```bash theme={null}
    vendor/bin/phpstan analyse src tests
    ```
  </Step>

  <Step title="Fest als Composer-Script verankern">
    Damit CI und lokale Umgebung denselben Befehl nutzen, definieren Sie ein Script in `composer.json`.

    ```json theme={null}
    {
        "scripts": {
            "analyse": "phpstan analyse"
        }
    }
    ```
  </Step>
</Steps>

## Larastan einrichten

Für Laravel-Pakete versteht PHPStan Container-Auflösung, Facades und Eloquent-Relations nicht ausreichend. Ergänzen Sie deshalb die PHPStan-Erweiterung Larastan.

<Steps>
  <Step title="Larastan hinzufügen">
    Der aktuelle Paketname lautet `larastan/larastan`. In älteren Artikeln taucht mitunter `nunomaduro/larastan` auf.

    ```bash theme={null}
    composer require --dev larastan/larastan:^3.0
    ```
  </Step>

  <Step title="Für Paketentwicklung Testbench installieren">
    Larastan startet zur Typ-Auflösung eine Laravel-Anwendungscontainer-Umgebung. Für die Einzelanalyse eines Laravel-Pakets ist häufig `orchestra/testbench` nötig.

    ```bash theme={null}
    composer require --dev orchestra/testbench
    ```
  </Step>

  <Step title="extension.neon einbinden">
    Includieren Sie in `phpstan.neon` die Larastan-Konfiguration.

    ```neon theme={null}
    includes:
        - vendor/larastan/larastan/extension.neon
    ```
  </Step>
</Steps>

## Konfiguration von phpstan.neon

`phpstan.neon` bündelt Analyse-Level, Zielpfade, Ausschlüsse und Ausnahmen. Realistischer als sofort „100 Punkte" ist eine Konfiguration, die sich schrittweise steigern lässt.

Beispiel für eine `phpstan.neon`:

```neon theme={null}
includes:
    - vendor/larastan/larastan/extension.neon

parameters:
    level: 5

    paths:
        - src
        - tests

    excludePaths:
        analyse:
            - vendor
            - workbench
            - bootstrap/cache/*

    ignoreErrors:
        -
            message: '#Call to an undefined method Illuminate\\Support\\HigherOrderCollectionProxy::#'
            path: tests/Fixtures/*
```

### Wahl des Levels 0–9

PHPStan lässt sich stufenweise einführen. Starten Sie mit einem Level, das Ihre Codebasis bewältigen kann, und steigern Sie es nach Fortschritt.

| Level | Passende Phase                                                           |
| ----- | ------------------------------------------------------------------------ |
| 0–3   | Zuerst unbekannte Klassen, Funktionen, Methodenaufrufe reduzieren        |
| 4–6   | Argumente, Rückgabetypen und Properties der Public API sauber typisieren |
| 7–9   | Nullable, Union und `mixed` strikt behandeln — Langzeitpflegephase       |

<Tip>
  PHPStan 2.x kennt auch Level 10; in Laravel-Paketen empfiehlt es sich, zunächst 5–7 zu stabilisieren und dann auf 8–9 zu gehen. Neue Pakete starten Sie besser gleich auf höherem Niveau — das erspart Rückschritte.
</Tip>

### `paths`

Geben Sie in `paths` die zu analysierenden Verzeichnisse explizit an. In Paketen lohnt es sich, neben `src` auch `tests` einzuschließen — die Typen sind dort häufiger brüchig.

### `excludePaths`

Schließen Sie nur Orte mit geringem Analyse-Nutzen aus, z. B. generierte Dateien, Caches oder eine Workbench-Verifikationsumgebung. Zu breit auszuschließen kaschiert echte Fehler.

### `ignoreErrors`

`ignoreErrors` ist letzte Wahl. Grenzen Sie Meldungen per Regex ein und ergänzen Sie `path`, um den Wirkungsbereich zu begrenzen. So können Sie später leichter zurückkehren, wenn Laravel oder Larastan Verbesserungen bringen.

## Häufige Typannotationen

Die Präzision von PHPStan und Larastan hängt stark von den PHPDocs ab. Vor allem `@param`, `@return`, `@var` und Generics (`@template`) lohnen sich in Laravel-Paketen.

```php theme={null}
<?php

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;

/**
 * @template TModel of Model
 */
final class ModelRepository
{
    /**
     * @param class-string<TModel> $modelClass
     */
    public function __construct(private string $modelClass)
    {
    }

    /**
     * @return TModel|null
     */
    public function find(int $id): ?Model
    {
        return $this->modelClass::query()->find($id);
    }

    /**
     * @return Collection<int, TModel>
     */
    public function all(): Collection
    {
        /** @var Collection<int, TModel> $models */
        $models = $this->modelClass::query()->get();

        return $models;
    }
}
```

Dieses Beispiel übermittelt PHPStan Folgendes:

* `@param class-string<TModel>` — der String ist keine beliebige Zeichenkette, sondern ein Model-Klassenname.
* `@return TModel|null` — `find()` liefert einen konkreten Model-Typ.
* `@var Collection<int, TModel>` — Key- und Value-Typ der Collection explizit machen.
* `@template TModel of Model` — ein wiederverwendbares generisches Repository.

## Laravel-spezifische Fallstricke

Die „bequeme Magie" von Laravel wird von statischen Analysewerkzeugen nicht automatisch verstanden. Sie müssen Typinformationen so ergänzen, dass die Analyzer sie erfassen.

### Facades

Bei eigenen Facades helfen PHPDoc-Annotationen der aufrufbaren Methoden sowohl der IDE als auch der statischen Analyse.

```php theme={null}
<?php

namespace Vendor\Package\Facades;

use Illuminate\Support\Facades\Facade;

/**
 * @method static string issueToken(int $userId)
 */
class Tokenizer extends Facade
{
    protected static function getFacadeAccessor(): string
    {
        return 'package.tokenizer';
    }
}
```

### Magic Methods

APIs auf Basis von `__call()` oder Macroable sind bequem, aber typunfreundlich. In der Public API sind Wrapper-Methoden mit klaren Signaturen sicherer.

<Warning>
  `ignoreErrors` einfach zu häufen, um die Analyse zu beruhigen, verdeckt echte Fehler in Facades oder Macros. Prüfen Sie zuerst, ob Sie es mit expliziten Methoden, typisierten Value Objects und PHPDoc lösen können.
</Warning>

### Typisierung von Eloquent-Modellen

Bei Eloquent-Relations und dynamischen Properties helfen `@property` und Generics an den Relations-Rückgaben.

```php theme={null}
<?php

namespace Vendor\Package\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

/**
 * @property-read Team $team
 */
class Member extends Model
{
    /**
     * @return BelongsTo<Team, self>
     */
    public function team(): BelongsTo
    {
        return $this->belongsTo(Team::class);
    }
}
```

## Automatisierung in der CI

Führen Sie die statische Analyse nicht nur lokal, sondern auch in der CI aus. Vor allem bei Paketen, die mehrere Laravel-Versionen unterstützen, empfiehlt sich eine Testmatrix analog zu [Versionskompatibilität von Paketen verwalten](/de/advanced/package-versioning), um Kompatibilität und Typsicherheit gemeinsam zu überwachen.

Ein Beispiel für `.github/workflows/static-analysis.yml`:

```yaml theme={null}
name: Static analysis

on:
  push:
  pull_request:

jobs:
  static-analysis:
    runs-on: ubuntu-latest

    strategy:
      fail-fast: false
      matrix:
        php: [8.2, 8.3, 8.4]
        laravel: ["^12.0", "^13.0"]
        include:
          - laravel: "^13.0"
            testbench: "^10.0"
          - laravel: "^12.0"
            testbench: "^9.0"

    name: PHP ${{ matrix.php }} - Laravel ${{ matrix.laravel }} - PHPStan

    steps:
      - uses: actions/checkout@v4

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: ${{ matrix.php }}
          extensions: dom, curl, libxml, mbstring, zip
          coverage: none

      - name: Install dependencies
        run: |
          composer require "laravel/framework:${{ matrix.laravel }}" \
                           "orchestra/testbench:${{ matrix.testbench }}" \
                           --no-interaction --no-update
          composer update --prefer-dist --no-interaction

      - name: Run static analysis
        run: vendor/bin/phpstan analyse --error-format=github
```

Das Beispiel verwendet dieselben Kombinationen von Laravel/Testbench wie die Testmatrix. Wenn Sie in Tests und statischer Analyse dieselben Kombinationen prüfen, entgeht Ihnen der Zustand „läuft, aber die Typen sind kaputt" seltener.

## Häufige Fehlalarme und Umgang

Wenn eine Warnung erscheint, fragen Sie sich zuerst: „Fehlt Typinformation?" Was wie ein Fehlalarm aussieht, ist oft nur ein unvollständiger PHPDoc.

### `@phpstan-ignore-next-line`

Als temporäre Umgehung geeignet — beschränken Sie es aber auf Zeilen, deren Grund Sie selbst erklären können.

```php theme={null}
// @phpstan-ignore-next-line Laravel-Macro wird zur Laufzeit registriert
$builder->whereLike('name', $keyword);
```

### `ignoreErrors`

Nur einsetzen, wenn derselbe Fehler an mehreren Stellen auftritt. Grenzen Sie stets über `path` ein und vermeiden Sie zu grobe Regex-Muster, die alles verschlucken.

```neon theme={null}
parameters:
    ignoreErrors:
        -
            message: '#Call to an undefined method Illuminate\\Database\\Eloquent\\Builder::whereLike\(\)#'
            path: tests/Fixtures/*
```

### Reihenfolge der Gegenmaßnahmen

1. PHPDoc ergänzen.
2. Rückgabetypen von Facades und Relations explizit machen.
3. `mixed` durch konkrete Typen ersetzen.
4. Erst danach — und nur mit Erklärung — Fehler ignorieren.

## Verwandte Seiten

<Columns cols={3}>
  <Card title="Laravel-Paketentwicklung" icon="box" href="/de/advanced/package-development">
    Grundlagen der Implementierung einschließlich Service Provider und veröffentlichter Ressourcen.
  </Card>

  <Card title="Laravel-Pakete mit Orchestra Testbench testen" icon="flask-conical" href="/de/advanced/package-testing">
    Testinfrastruktur, die zusammen mit statischer Analyse betrieben wird.
  </Card>

  <Card title="Versionskompatibilität von Paketen verwalten" icon="git-branch" href="/de/advanced/package-versioning">
    Laravel-/PHP-Kompatibilitätstabelle und die Matrix-Strategie in GitHub Actions.
  </Card>
</Columns>


## Related topics

- [Laravel Package Skeleton – Starter-Template für offizielle Pakete](/de/blog/package-skeleton-introduction.md)
- [Collection Deep Dive](/de/advanced/collection-deep-dive.md)
- [Laravels neues Ökosystem zur Code-Analyse – surveyor / ranger / roster](/de/blog/laravel-ecosystem-analysis.md)
- [Laravel PAO – Output-Optimierungstool für KI-Agenten](/de/blog/pao-introduction.md)
- [Laravel Sentinel – Analyse der Route-Schutz-Middleware](/de/blog/sentinel-introduction.md)
