Zum Hauptinhalt springen
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.
Diese Seite ergänzt Laravel-Paketentwicklung, Laravel-Pakete mit Orchestra Testbench testen und Versionskompatibilität von Paketen verwalten. Ergänzen Sie Implementierung, Test und Versionsstrategie um statische Analyse, um Pakete langfristig wartbar zu halten.

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.
1

PHPStan als Dev-Abhängigkeit hinzufügen

composer require --dev phpstan/phpstan:^2.0
2

Zunächst direkt Verzeichnisse analysieren

In Paketen sind meist src und tests die ersten Ziele.
vendor/bin/phpstan analyse src tests
3

Fest als Composer-Script verankern

Damit CI und lokale Umgebung denselben Befehl nutzen, definieren Sie ein Script in composer.json.
{
    "scripts": {
        "analyse": "phpstan analyse"
    }
}

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.
1

Larastan hinzufügen

Der aktuelle Paketname lautet larastan/larastan. In älteren Artikeln taucht mitunter nunomaduro/larastan auf.
composer require --dev larastan/larastan:^3.0
2

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.
composer require --dev orchestra/testbench
3

extension.neon einbinden

Includieren Sie in phpstan.neon die Larastan-Konfiguration.
includes:
    - vendor/larastan/larastan/extension.neon

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:
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.
LevelPassende Phase
0–3Zuerst unbekannte Klassen, Funktionen, Methodenaufrufe reduzieren
4–6Argumente, Rückgabetypen und Properties der Public API sauber typisieren
7–9Nullable, Union und mixed strikt behandeln — Langzeitpflegephase
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.

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

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|nullfind() 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

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.
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.

Typisierung von Eloquent-Modellen

Bei Eloquent-Relations und dynamischen Properties helfen @property und Generics an den Relations-Rückgaben.
<?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, um Kompatibilität und Typsicherheit gemeinsam zu überwachen. Ein Beispiel für .github/workflows/static-analysis.yml:
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.
// @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.
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

Laravel-Paketentwicklung

Grundlagen der Implementierung einschließlich Service Provider und veröffentlichter Ressourcen.

Laravel-Pakete mit Orchestra Testbench testen

Testinfrastruktur, die zusammen mit statischer Analyse betrieben wird.

Versionskompatibilität von Paketen verwalten

Laravel-/PHP-Kompatibilitätstabelle und die Matrix-Strategie in GitHub Actions.
Zuletzt geändert am 13. Juli 2026