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

# Analyse statique de packages (PHPStan / Larastan)

> Installation, configuration, annotations de type et exécution automatique en CI de PHPStan et Larastan pour améliorer la sûreté de typage et la maintenabilité de vos packages Laravel.

Un package Laravel n'est pas terminé une fois publié. Pour le maintenir sur plusieurs années tout en suivant les évolutions de Laravel, de PHP et des packages tiers, il faut faire tourner en continu non seulement les tests, mais aussi l'analyse statique.

<Info>
  Cette page complète [Développement de packages Laravel](/fr/advanced/package-development), [Tester des packages Laravel avec Orchestra Testbench](/fr/advanced/package-testing) et [Gestion de la compatibilité de versions de package](/fr/advanced/package-versioning). Ajouter de l'analyse statique à votre stratégie d'implémentation, de tests et de versionnage rend le package plus facile à maintenir sur le long terme.
</Info>

## Qu'est-ce que l'analyse statique

L'analyse statique consiste à détecter les incohérences de types et les bugs potentiels sans exécuter le code. Comme les packages Laravel utilisent beaucoup de mécanismes dynamiques (service container, façades, Eloquent), l'analyse statique attrape tôt des problèmes que les seuls tests d'exécution laissent passer.

L'introduction de l'analyse statique offre en particulier les bénéfices suivants :

* **Sûreté de typage améliorée** — les arguments ou valeurs de retour incorrects sont détectés avant la revue.
* **Détection précoce des bugs** — les appels à des méthodes inexistantes ou les oublis de nullable sont repérés avant les tests.
* **Meilleure auto-complétion IDE** — un PHPDoc soigné et l'usage des Generics améliorent la précision.
* **Stabilité de la maintenance longue durée** — plus facile de repérer ce qui casse à chaque montée de Laravel ou PHP.

## Installer PHPStan

Commencez par mettre en place une base d'analyse avec PHPStan seul. PHPStan 2.x est plus strict qu'auparavant sur `mixed` et les nullables, ce qui est aussi l'occasion de nettoyer l'API publique de votre package.

<Steps>
  <Step title="Ajouter PHPStan aux dépendances de dev">
    ```bash theme={null}
    composer require --dev phpstan/phpstan:^2.0
    ```
  </Step>

  <Step title="Analyser d'abord les répertoires ciblés directement">
    Pour un package, on commence souvent par `src` et `tests`.

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

  <Step title="Fixer la commande dans les scripts Composer">
    Pour utiliser la même commande en local et en CI, définir un script dans `composer.json` facilite l'exploitation.

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

## Installer Larastan

Avec PHPStan seul, les spécificités Laravel (résolution via le container, façades, relations Eloquent) sont mal comprises. Utilisez donc Larastan, l'extension Laravel de PHPStan, en complément.

<Steps>
  <Step title="Ajouter Larastan">
    Le package actuel s'appelle `larastan/larastan`. Dans d'anciens articles, on trouve encore `nunomaduro/larastan`.

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

  <Step title="Pour du développement de package, installer aussi Testbench">
    Larastan démarre le conteneur d'application Laravel pour résoudre les types. Pour analyser un package Laravel isolément, `orchestra/testbench` peut être nécessaire.

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

  <Step title="Inclure extension.neon">
    Dans `phpstan.neon`, incluez la configuration de Larastan.

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

## Configurer phpstan.neon

`phpstan.neon` centralise le niveau d'analyse, les chemins ciblés, les exclusions et les règles d'exception. Pour un package Laravel, plutôt que de viser 100 % dès le départ, il est plus réaliste de mettre en place une configuration que vous pourrez faire progresser.

Voici un exemple de `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/*
```

### Choisir un niveau entre 0 et 9

PHPStan se met en place graduellement. Commencez par le niveau que votre code base peut supporter, puis augmentez-le au fur et à mesure des corrections.

| Niveau | Étape adaptée                                                                        |
| ------ | ------------------------------------------------------------------------------------ |
| 0-3    | Réduire d'abord les appels de classes / fonctions / méthodes inconnues               |
| 4-6    | Fiabiliser les arguments, valeurs de retour et types de propriétés de l'API publique |
| 7-9    | Traiter strictement nullable, union et `mixed` en phase de maintenance longue durée  |

<Tip>
  PHPStan 2.x propose aussi le niveau 10, mais pour un package Laravel, il est réaliste de stabiliser d'abord 5-7 avant de passer à 8-9. Pour un nouveau package, démarrer directement à un niveau élevé évite de refaire le travail.
</Tip>

### `paths`

`paths` déclare explicitement les répertoires à analyser. Pour un package, il est efficace d'inclure `tests` en plus de `src`, car les types y sont facilement bancals.

### `excludePaths`

N'excluez que les endroits à faible valeur pour l'analyse statique : fichiers générés, caches, Workbench de vérification. Une exclusion trop large masque des erreurs que vous voudriez pourtant voir.

### `ignoreErrors`

`ignoreErrors` est un dernier recours. Filtrez le message par regex et associez toujours un `path` pour limiter la portée. Cela facilite le retour arrière quand Laravel ou Larastan s'améliorent.

## Annotations de type courantes

La précision de PHPStan et Larastan dépend beaucoup de la manière d'écrire les PHPDoc. Dans un package Laravel, il est particulièrement rentable de bien renseigner `@param`, `@return`, `@var` et les Generics (`@template`).

```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;
    }
}
```

Dans cet exemple, on transmet à PHPStan les informations suivantes :

* `@param class-string<TModel>` — indique que la chaîne n'est pas quelconque mais un nom de classe Model.
* `@return TModel|null` — indique que `find()` retourne le type concret du modèle.
* `@var Collection<int, TModel>` — précise les types de clé et de valeur de la collection.
* `@template TModel of Model` — exprime un repository générique réutilisable.

## Points d'attention propres à Laravel

La « magie pratique » de Laravel ne se transmet pas telle quelle à l'analyse statique. Il faut ajouter côté package des informations de type que l'outil peut comprendre.

### Façades

Pour une façade personnalisée, décrire les méthodes appelées par les utilisateurs en PHPDoc profite à la fois à l'IDE et à l'analyse statique.

```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';
    }
}
```

### Méthodes magiques

Les API qui reposent sur `__call()` ou Macroable sont pratiques, mais fragiles pour le typage. Pour une API publique, ajouter des méthodes wrapper explicites — dont les arguments et le retour sont connus — est plus sûr.

<Warning>
  Multiplier les `ignoreErrors` juste pour l'analyse statique cache la manière dont les façades ou macros peuvent réellement casser. Cherchez d'abord à résoudre le problème avec des méthodes explicites, des value objects typés ou des ajouts de PHPDoc.
</Warning>

### Typage des modèles Eloquent

Pour les relations et propriétés dynamiques d'Eloquent, combiner `@property` et les Generics des relations est efficace.

```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);
    }
}
```

## Exécution automatique en CI

Exécutez l'analyse statique non seulement en local, mais toujours en CI. Pour un package qui prend en charge plusieurs versions de Laravel, appliquer la même approche que la matrice de tests de [Gestion de la compatibilité de versions de package](/fr/advanced/package-versioning) permet de surveiller simultanément la compatibilité et la sûreté de typage.

Voici un exemple de `.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
```

Cet exemple utilise la même table de correspondance Laravel / Testbench que la matrice de tests. Surveiller les mêmes combinaisons pour tests et analyse statique aide à éviter les situations où « ça tourne, mais les types sont cassés ».

## Faux positifs fréquents et comment les traiter

Face à un avertissement de l'analyse statique, demandez-vous d'abord s'il ne manque pas d'information de type. Ce qui ressemble à un faux positif n'est souvent qu'un PHPDoc incomplet.

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

Utilisable comme contournement temporaire, mais réservez-le aux lignes dont vous pouvez expliquer la raison.

```php theme={null}
// @phpstan-ignore-next-line macro Laravel enregistrée à l'exécution
$builder->whereLike('name', $keyword);
```

### `ignoreErrors`

À considérer uniquement quand la même erreur apparaît à plusieurs endroits. Limitez toujours la portée avec un `path` et n'utilisez pas d'expression régulière trop lâche qui étoufferait tout.

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

### Ordre de priorité des corrections

1. Ajouter des PHPDoc.
2. Déclarer explicitement les types de retour des façades et relations.
3. Remplacer les `mixed` par des types concrets.
4. Ignorer seulement les faux positifs que vous pouvez expliquer.

## Pages associées

<Columns cols={3}>
  <Card title="Développement de packages Laravel" icon="box" href="/fr/advanced/package-development">
    Passez en revue les fondations d'un package, service providers et ressources publiées.
  </Card>

  <Card title="Tester des packages Laravel avec Orchestra Testbench" icon="flask-conical" href="/fr/advanced/package-testing">
    Découvrez l'infrastructure de test à combiner avec l'analyse statique.
  </Card>

  <Card title="Gestion de la compatibilité de versions de package" icon="git-branch" href="/fr/advanced/package-versioning">
    Passez en revue la table de compatibilité Laravel / PHP et la stratégie de matrice GitHub Actions.
  </Card>
</Columns>


## Related topics

- [Collection Deep Dive](/fr/advanced/collection-deep-dive.md)
- [Laravel Package Skeleton — le template de démarrage pour packages officiels](/fr/blog/package-skeleton-introduction.md)
- [Le nouvel écosystème d'analyse de code Laravel — surveyor / ranger / roster](/fr/blog/laravel-ecosystem-analysis.md)
- [Laravel Console Starter](/fr/packages/laravel-console-starter/index.md)
- [Laravel PAO — outil d'optimisation des sorties pour les agents IA](/fr/blog/pao-introduction.md)
