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

# Registrare driver Storage in un pacchetto e risolverli di nuovo

> Analisi del FilesystemManager di Laravel 13: registrazione con Storage::extend(), conservazione delle istanze dei dischi, nuova risoluzione dopo una modifica della configurazione e verifiche che non dipendono da fake.

Quando vuoi offrire funzionalità di storage da un pacchetto, tieni separate **la registrazione del modo in cui viene creato il driver** e **la creazione dei dischi dell'utente**. Se il solo avvio del provider non apre connessioni esterne né esegue operazioni sui file, è più difficile compromettere l'avvio degli ambienti che non usano questa funzionalità.

Questa pagina fa riferimento all'implementazione di Laravel Framework `v13.37.0`. Per le operazioni di base consulta [Storage dei file](/it/filesystem); per il caricamento dei provider consulta [Rilevamento automatico dei pacchetti](/it/advanced/package-discovery).

## Distinguere il nome del driver dal nome del disco

Il primo argomento di `Storage::extend()` è il **nome del driver**. L'argomento di `Storage::disk()`, invece, è il **nome del disco** definito in `filesystems.disks`. Puoi definire più dischi che usano lo stesso driver.

| Elemento | Esempio in questa pagina | Ruolo |
| - | - | - |
| Nome del driver | `acme-archive-local` | Identificatore della callback che crea il disco |
| Nome del disco | `reports`, `exports` | Identificatore della configurazione e dell'istanza già creata |
| Configurazione del disco | `root`, `throw` ecc. | Valori passati alla callback quando viene creato quel disco |

`FilesystemManager::resolve()` cerca un processo di creazione personalizzato corrispondente al `driver` della configurazione e, se esiste, lo chiama prima dei driver integrati. Usare `local` o `s3` come nome dell'estensione sostituisce il processo di creazione esistente, quindi scegli un nome specifico del pacchetto.

## Nel provider registrare solo il modo di creare

Ecco un esempio minimo che riutilizza il processo di creazione del driver locale standard di Laravel, per capire il percorso di registrazione. Se l'obiettivo è solo il salvataggio locale, il normale driver `local` è sufficiente. Per offrire un backend proprio, sostituisci questo processo con la costruzione di un adapter Flysystem avvolto nel `FilesystemAdapter` di Laravel, come nell'esempio della documentazione ufficiale.

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

namespace Acme\Archive;

use Illuminate\Contracts\Foundation\Application;
use Illuminate\Filesystem\FilesystemAdapter;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\ServiceProvider;
use InvalidArgumentException;

class ArchiveServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Storage::extend('acme-archive-local', static function (
            Application $app,
            array $config,
        ): FilesystemAdapter {
            if (! is_string($config['root'] ?? null) || $config['root'] === '') {
                throw new InvalidArgumentException('Archive disk requires a root.');
            }

            return $app['filesystem']->createLocalDriver($config);
        });
    }
}
```

Questo provider viene [registrato nel pacchetto nel modo consueto](/it/advanced/package-discovery). Perché sia disponibile in HTTP, in Artisan e nei worker delle code, non limitare la registrazione con `runningInConsole()`. Inoltre, non rendere un [provider differito](/it/advanced/deferred-provider) un provider che si occupa solo di registrare l'estensione.

La callback riceve l'applicazione e **l'intera configurazione del disco da risolvere**. Esegui la validazione della configurazione e la creazione dei client al suo interno, e non eseguire operazioni sui file in `boot()`. Nell'esempio, `createLocalDriver()` può creare una directory al momento della creazione, quindi è importante separare il momento della registrazione da quello della creazione.

<Tip>
  `FilesystemManager::extend()` associa il `$this` di una normale closure al Manager. Non dare per scontato di poter usare il `$this` del provider: usando una closure `static` e l'argomento `$app` come in questo esempio, le dipendenze diventano esplicite.
</Tip>

L'utente aggiunge la configurazione all'array `disks` di `config/filesystems.php`.

```php theme={null}
'reports' => [
    'driver' => 'acme-archive-local',
    'root' => storage_path('app/private/reports'),
    'throw' => true,
],
'exports' => [
    'driver' => 'acme-archive-local',
    'root' => storage_path('app/private/exports'),
    'throw' => true,
],
```

Chi usa il disco indica il nome del disco, non il nome del driver.

```php theme={null}
use Illuminate\Support\Facades\Storage;

Storage::disk('reports')->put('summary.txt', 'Monthly summary');
```

<Info>
  Questo esempio mostra solo il percorso di creazione per il salvataggio locale. La distribuzione di file tramite `serve` e la fornitura di URL temporanei non sono trattate. Anche se un adapter proprio supporta la generazione di URL, la visibilità, la sola lettura e così via, verifica ciascuna implementazione e i pacchetti di dipendenza necessari, senza presumere che basti passare una chiave di configurazione per attivarle.
</Info>

## I dischi con nome vengono conservati dopo la creazione

`disk('reports')` non chiama la callback ogni volta. Il metodo `get()` del Manager dà la precedenza all'istanza già creata presente nell'array interno `$disks`. Solo se il disco non è ancora stato creato si passa per `resolve()`, e il risultato viene conservato usando il nome del disco come chiave.

```mermaid theme={null}
flowchart TD
    A["boot() del provider"] --> B["Registrare il processo di creazione con extend()"]
    B --> C["Storage::disk('reports')"]
    C --> D{"reports è già stato creato?"}
    D -->|Sì| E["Restituire l'istanza conservata"]
    D -->|No| F["Leggere driver e passare la configurazione al processo di creazione"]
    F --> G["Conservare il risultato come reports"]
    G --> E
```

Di conseguenza, eseguire le seguenti operazioni nello stesso processo non aggiorna automaticamente un disco già creato.

* Modificare `filesystems.disks.reports` con `config()`.
* Chiamare di nuovo `Storage::extend()` per lo stesso nome di driver.

`FilesystemServiceProvider` registra anche il Manager stesso come singleton. Nei processi di lunga durata, non presumere che i dischi vengano sempre ricreati a ogni richiesta o a ogni job.

## Dopo una modifica della configurazione, risolvere di nuovo solo i dischi necessari

Per modificare la configurazione e verificarla nello stesso processo, tieni separati l'aggiornamento della configurazione e la rimozione del disco conservato.

```php theme={null}
use Illuminate\Support\Facades\Storage;

$before = Storage::disk('reports');

config(['filesystems.disks.reports.root' => storage_path('app/private/reports-v2')]);
Storage::forgetDisk('reports');

$after = Storage::disk('reports');
```

`forgetDisk()` rimuove il nome indicato dall'array di conservazione del Manager. La chiamata successiva a `disk()` rilegge la configurazione corrente. Nella versione esaminata anche `purge()` si limita a rimuovere il nome indicato e non chiama alcun metodo di chiusura della connessione di un backend proprio.

<Warning>
  Questo non riscrive i riferimenti conservati da chi usa il disco, come `$before`. Lo stesso vale quando un servizio singleton conserva un disco vecchio. Non usare `forgetDisk()` come meccanismo per aggiornare in un colpo solo tutti i riferimenti o gli altri processi.
</Warning>

Per le modifiche di configurazione in produzione o gli aggiornamenti del pacchetto, ricrea la cache della configurazione secondo il normale deploy e riavvia anche i worker di lunga durata. La cache della configurazione e l'array di conservazione dei dischi di questo processo sono due cose distinte.

### Usare build per una configurazione temporanea

Se non vuoi modificare una configurazione condivisa con nome, puoi usare un [disco on demand](/it/filesystem).

```php theme={null}
use Illuminate\Support\Facades\Storage;

$disk = Storage::build([
    'driver' => 'acme-archive-local',
    'root' => storage_path('app/private/one-off-export'),
    'throw' => true,
]);
```

`build()` chiama direttamente `resolve()` con la configurazione indicata e non aggiunge il risultato all'array di conservazione dei dischi con nome. La registrazione del driver personalizzato resta necessaria, ma ogni chiamata passa per il processo di creazione. Anche quando usi destinazioni dinamiche, non progettare il sistema in modo che la destinazione o l'endpoint di connessione possano essere scelti senza limiti a partire dall'input dell'utente.

## Testare il percorso di creazione separatamente da fake

`Storage::fake('reports')` sostituisce quel disco con un disco locale di test tramite il metodo `set()` del Manager. È comodo per testare le operazioni sui file dell'applicazione, ma **non verifica che il processo di creazione personalizzato del pacchetto sia registrato ed eseguito correttamente**.

Dopo aver caricato `ArchiveServiceProvider` nell'[ambiente di test del pacchetto](/it/advanced/package-testing), verifica separatamente i punti seguenti.

| Test | Cosa verificare |
| - | - |
| Avvio normale | Se nessun disco viene usato, la validazione della configurazione e le operazioni sui file del processo di creazione non partono |
| Dischi con nome | `reports` ed `exports` ricevono ciascuno la propria configurazione e sono istanze diverse |
| Nuovo recupero dello stesso nome | Chiamare `disk('reports')` due volte restituisce la stessa istanza |
| Modifica della configurazione | Cambiando solo la configurazione si ottiene la stessa istanza; dopo `forgetDisk()` l'istanza è diversa |
| On demand | Chiamare `build()` due volte con la stessa configurazione restituisce istanze diverse |
| Configurazione non valida | In questo esempio, la risoluzione di un disco senza `root` genera un'eccezione |
| Lettura e scrittura reali | Verificare salvataggio, recupero ed eliminazione in una directory dedicata ai test, ripulendo alla fine |
| Con cache della configurazione | Anche in un'applicazione di verifica appena avviata il driver è registrato e può essere risolto |

Per un backend esterno proprio, separa i test di creazione che non usano la rete dai test di connessione in un ambiente di verifica preparato esplicitamente. Non considerare il successo di fake come prova di compatibilità con il servizio reale.

## Checklist per la manutenzione a lungo termine

* Documentare come specifica pubblica il nome del driver, le chiavi di configurazione, l'API del valore restituito e la gestione delle eccezioni e di `throw`.
* Usare un nome di estensione che non entri in conflitto con i driver standard o con altri pacchetti.
* Non risolvere né usare dischi con il solo avvio del provider.
* Durante le modifiche di configurazione, distinguere cache della configurazione, array di conservazione del Manager, riferimenti di chi usa il disco e altri processi.
* Per ogni versione di Laravel supportata, verificare in modo continuativo creazione, nuova risoluzione e operazioni reali sui file.

## Fonti primarie consultate

* [Documentazione ufficiale di Laravel: filesystem personalizzati](https://github.com/laravel/docs/blob/12080c72699b/filesystem.md#custom-filesystems)
* [FilesystemManager: disk, build, resolve, forgetDisk, purge, extend](https://github.com/laravel/framework/blob/v13.37.0/src/Illuminate/Filesystem/FilesystemManager.php)
* [FilesystemServiceProvider: registrazione del Manager come singleton](https://github.com/laravel/framework/blob/v13.37.0/src/Illuminate/Filesystem/FilesystemServiceProvider.php)
* [Facade Storage: sostituzione con un disco locale tramite fake](https://github.com/laravel/framework/blob/v13.37.0/src/Illuminate/Support/Facades/Storage.php)
* [Test ufficiali di Laravel: creazione, rimozione e closure personalizzate dei dischi](https://github.com/laravel/framework/blob/v13.37.0/tests/Filesystem/FilesystemManagerTest.php)


## Related topics

- [Pacchetto core e driver personalizzati - Feedable](/it/packages/feedable/core.md)
- [Registrazione e cache dei listener di eventi di un pacchetto](/it/advanced/package-events.md)
- [Estensioni Blade di un pacchetto e cache di compilazione](/it/advanced/package-blade-extensions.md)
- [File storage](/it/filesystem.md)
- [Registrazione dei comandi Artisan di un pacchetto e risoluzione delle dipendenze](/it/advanced/package-commands.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.