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

# Analisi statica dei pacchetti (PHPStan / Larastan)

> Setup, configurazione, annotazioni di tipo ed esecuzione automatica in CI per migliorare type-safety e manutenibilità dei pacchetti Laravel con PHPStan e Larastan.

Un pacchetto Laravel non termina al primo rilascio. Per mantenerlo per anni tenendo il passo con gli aggiornamenti di Laravel, PHP e delle dipendenze, oltre ai test devi far girare in modo continuo anche l'analisi statica.

<Info>
  Questa pagina è una guida complementare a [Sviluppo di pacchetti Laravel](/it/advanced/package-development), [Testare pacchetti Laravel con Orchestra Testbench](/it/advanced/package-testing) e [Gestire la compatibilità tra versioni dei pacchetti](/it/advanced/package-versioning). Aggiungere l'analisi statica a implementazione, test e strategia di versioning rende il pacchetto più stabile a lungo termine.
</Info>

## Cos'è l'analisi statica

L'analisi statica rileva incongruenze di tipo e bug potenziali senza eseguire il codice. In un pacchetto Laravel — service container, facade, Eloquent — ci sono molti meccanismi dinamici: verifiche a runtime da sole rischiano di lasciare passare problemi. L'analisi statica li intercetta in anticipo.

Introducendola ottieni in particolare questi vantaggi.

* **Migliore type-safety** — rilevi argomenti o valori di ritorno sbagliati già prima della review
* **Bug scoperti prima** — trovi chiamate a metodi inesistenti o nullable dimenticati prima dei test
* **Autocompletamento IDE migliore** — sistemando PHPDoc e generics l'accuratezza dell'IDE aumenta
* **Manutenzione a lungo termine più stabile** — durante gli upgrade Laravel/PHP individui prima cosa si rompe

## Setup di PHPStan

Prima predisponi la base di analisi con solo PHPStan. PHPStan 2.x gestisce `mixed` e nullable in modo più rigido: è una buona occasione per sistemare le API pubbliche del pacchetto.

<Steps>
  <Step title="Aggiungere PHPStan come dipendenza di sviluppo">
    ```bash theme={null}
    composer require --dev phpstan/phpstan:^2.0
    ```
  </Step>

  <Step title="Prima analizza direttamente le directory target">
    Nei pacchetti spesso si parte da `src` e `tests`.

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

  <Step title="Fissarlo come script Composer">
    Definisci uno script in `composer.json` così CI e locale usano lo stesso comando.

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

## Setup di Larastan

Nei pacchetti Laravel, il solo PHPStan non capisce del tutto meccanismi Laravel-specifici come risoluzione dal container, facade e relazioni Eloquent. Perciò affianchi Larastan, l'estensione Laravel di PHPStan.

<Steps>
  <Step title="Aggiungere Larastan">
    Il nome attuale del pacchetto è `larastan/larastan`. Negli articoli vecchi potresti trovare `nunomaduro/larastan`.

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

  <Step title="Per lo sviluppo di pacchetti installa anche Testbench">
    Larastan avvia il container Laravel per risolvere i tipi. Nell'analisi standalone di un pacchetto Laravel a volte serve `orchestra/testbench`.

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

  <Step title="Includere extension.neon">
    In `phpstan.neon` includi la configurazione di Larastan.

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

## Configurazione di phpstan.neon

`phpstan.neon` è il file centrale che raccoglie livello di analisi, path da analizzare, path da escludere e regole di eccezione. Per un pacchetto Laravel è più realistico partire da un setup che puoi far salire nel tempo, piuttosto che puntare al 100% da subito.

Esempio di `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/*
```

### Come scegliere il livello 0–9

PHPStan si introduce in modo graduale. Parti dal livello che la codebase attuale riesce a superare e alza man mano che sistemi le cose.

| Livello | Fase indicata                                                                          |
| ------- | -------------------------------------------------------------------------------------- |
| 0–3     | Vuoi ridurre chiamate a classi, funzioni o metodi sconosciuti                          |
| 4–6     | Vuoi sistemare argomenti, valori di ritorno e proprietà dell'API pubblica              |
| 7–9     | Fase di manutenzione a lungo termine: gestisci nullable, union, `mixed` in modo rigido |

<Tip>
  PHPStan 2.x ha anche il livello 10, ma nei pacchetti Laravel è realistico stabilizzare prima 5–7 e poi passare a 8–9. Per un pacchetto nuovo, partire già alto riduce il lavoro di ritorno.
</Tip>

### `paths`

In `paths` indichi esplicitamente le directory da analizzare. Includere non solo `src` ma anche `tests` (dove i tipi tendono a rilassarsi) è efficace.

### `excludePaths`

Escludi solo i luoghi in cui l'analisi statica ha poco valore: file generati, cache, Workbench di verifica. Escludere troppo nasconde gli errori che invece vorresti vedere.

### `ignoreErrors`

`ignoreErrors` è l'ultima risorsa. Restringi il messaggio con una regex e limita l'impatto con `path`. Così quando Laravel o Larastan miglioreranno, sarà più facile ripristinare.

## Annotazioni di tipo frequenti

L'accuratezza di PHPStan e Larastan cambia molto in base a come scrivi il PHPDoc. Nei pacchetti Laravel vale la pena sistemare in particolare `@param`, `@return`, `@var` e i 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;
    }
}
```

In questo esempio passi a PHPStan queste informazioni.

* `@param class-string<TModel>` — indica che la stringa non è arbitraria ma il nome di una classe Model
* `@return TModel|null` — comunica che `find()` restituisce un tipo Model concreto
* `@var Collection<int, TModel>` — esplicita i tipi key/value della collection
* `@template TModel of Model` — descrive un generic repository riutilizzabile

## Punti specifici di Laravel

La "magic" comoda di Laravel non è visibile all'analisi statica così com'è. Devi aggiungere informazioni di tipo dal lato pacchetto per portarle nella forma che l'analizzatore comprende.

### Facade

Nei facade custom, integrando i metodi richiamati dagli utenti con PHPDoc, ottieni benefici sia per IDE sia per analisi statica.

```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 method

Le API che si basano su `__call()` o su Macroable sono comode, ma è facile che il tipo salti. Se sono API pubbliche, aggiungere wrapper con argomenti e valori di ritorno chiari è più sicuro.

<Warning>
  Continuare ad aggiungere `ignoreErrors` solo per far tacere l'analisi statica finisce per nascondere i veri modi in cui facade e macro si rompono. Prima prova con metodi espliciti, value object tipizzati e PHPDoc.
</Warning>

### Tipizzazione dei modelli Eloquent

Per relazioni e proprietà dinamiche di Eloquent, la combinazione di `@property` e generics sulle relation è 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);
    }
}
```

## Esecuzione automatica in CI

Esegui l'analisi statica anche in CI, non solo in locale. In particolare, se il pacchetto supporta più versioni di Laravel, usare la stessa logica della test matrix di [Gestire la compatibilità tra versioni dei pacchetti](/it/advanced/package-versioning) permette di controllare in parallelo compatibilità e type-safety.

Esempio di `.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
```

In questo esempio uso la stessa tabella Laravel/Testbench della test matrix. Controllando la stessa combinazione sia con test sia con analisi statica, riduci il rischio di uno stato "gira ma i tipi sono rotti".

## Falsi positivi frequenti e come gestirli

Davanti a un warning di analisi statica chiediti prima "manca qualche informazione di tipo?". Spesso un falso positivo è in realtà un PHPDoc mancante.

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

Utile come workaround temporaneo, ma limitalo alle righe di cui puoi spiegare tu stesso il motivo.

```php theme={null}
// @phpstan-ignore-next-line la macro di Laravel viene registrata a runtime
$builder->whereLike('name', $keyword);
```

### `ignoreErrors`

Da considerare solo quando lo stesso errore appare in più punti. Restringi sempre il path e non usare regex generici che nascondono tutto.

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

### Ordine di priorità

1. Aggiungi PHPDoc
2. Esplicita i tipi di ritorno di facade e relation
3. Sostituisci `mixed` con tipi concreti
4. Ignora solo i falsi positivi che sai spiegare

## Pagine correlate

<Columns cols={3}>
  <Card title="Sviluppo di pacchetti Laravel" icon="box" href="/it/advanced/package-development">
    Rivedi le basi di implementazione di un pacchetto, service provider e risorse pubblicate incluse.
  </Card>

  <Card title="Testare pacchetti Laravel con Orchestra Testbench" icon="flask-conical" href="/it/advanced/package-testing">
    Rivedi la struttura di test per pacchetti da combinare con l'analisi statica.
  </Card>

  <Card title="Gestire la compatibilità tra versioni dei pacchetti" icon="git-branch" href="/it/advanced/package-versioning">
    Rivedi la tabella di compatibilità Laravel/PHP e la strategia matrix di GitHub Actions.
  </Card>
</Columns>


## Related topics

- [Laravel Package Skeleton — template starter per pacchetti ufficiali](/it/blog/package-skeleton-introduction.md)
- [Il nuovo ecosistema di analisi del codice Laravel — surveyor / ranger / roster](/it/blog/laravel-ecosystem-analysis.md)
- [Iniziare a testare Laravel con Pest PHP](/it/blog/pest-introduction.md)
- [Laravel PAO — strumento di ottimizzazione dell'output per agenti AI](/it/blog/pao-introduction.md)
- [Collection Deep Dive](/it/advanced/collection-deep-dive.md)
