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

# Storage-drivers registreren in een package en opnieuw resolven

> Op basis van de FilesystemManager van Laravel 13: registreren met Storage::extend(), het vasthouden van disk-instanties, opnieuw resolven na een configuratiewijziging en verificatie die niet afhankelijk is van fake.

Wanneer je vanuit een package opslagfunctionaliteit aanbiedt, scheid je **het registreren van hoe de driver wordt aangemaakt** van **het aanmaken van de disks van de gebruiker**. Als het opstarten van de provider alleen nog geen externe verbindingen of bestandsbewerkingen start, breek je minder snel het opstarten van omgevingen die de functionaliteit niet gebruiken.

Deze pagina is gecontroleerd aan de hand van de implementatie van Laravel Framework `v13.37.0`. Zie [Bestandsopslag](/nl/filesystem) voor de basisbewerkingen en [Automatische packagedetectie](/nl/advanced/package-discovery) voor het laden van providers.

## Drivernaam en disknaam onderscheiden

Het eerste argument van `Storage::extend()` is de **drivernaam**. Het argument van `Storage::disk()` is daarentegen de **disknaam** die in `filesystems.disks` is gedefinieerd. Je kunt meerdere disks definiëren die dezelfde driver gebruiken.

| Onderdeel | Voorbeeld op deze pagina | Rol |
| - | - | - |
| Drivernaam | `acme-archive-local` | Identificatie van de callback die de disk aanmaakt |
| Disknaam | `reports`, `exports` | Identificatie van de configuratie en de al aangemaakte instantie |
| Diskconfiguratie | `root`, `throw` enz. | Waarden die bij het aanmaken van die disk aan de callback worden doorgegeven |

`FilesystemManager::resolve()` zoekt een aangepaste aanmaakroutine die past bij de `driver` uit de configuratie en roept die, als hij bestaat, aan vóór de ingebouwde drivers. Als je `local` of `s3` als extensienaam gebruikt, vervang je de bestaande aanmaakroutine. Kies daarom een packagespecifieke naam.

## In de provider alleen de aanmaakwijze registreren

Hieronder staat een minimaal voorbeeld dat de aanmaakroutine van de standaard lokale driver van Laravel hergebruikt, om het registratiepad te begrijpen. Als je alleen lokaal wilt opslaan, volstaat de gewone `local`-driver. Wil je een eigen backend aanbieden, vervang deze routine dan door het opbouwen van een Flysystem-adapter die je in de `FilesystemAdapter` van Laravel verpakt, zoals in het voorbeeld uit de officiële documentatie.

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

Deze provider [registreer je op de gebruikelijke manier in het package](/nl/advanced/package-discovery). Beperk de registratie niet met `runningInConsole()`, zodat hij beschikbaar is in HTTP, Artisan en queue-workers. Maak een provider die alleen de extensie registreert ook geen [uitgestelde provider](/nl/advanced/deferred-provider).

De callback ontvangt de applicatie en **de volledige configuratie van de disk die wordt geresolved**. Voer de validatie van de configuratie en het aanmaken van clients binnen de callback uit, en voer in `boot()` geen bestandsbewerkingen uit. `createLocalDriver()` uit het voorbeeld kan bij het aanmaken een map aanmaken, dus het is belangrijk om het registratiemoment en het aanmaakmoment te scheiden.

<Tip>
  `FilesystemManager::extend()` bindt `$this` van een gewone closure aan de Manager. Ga er niet van uit dat je `$this` van de provider kunt gebruiken. Met een `static` closure en het argument `$app` zoals in dit voorbeeld worden de afhankelijkheden expliciet.
</Tip>

De gebruiker voegt de configuratie toe aan de `disks`-array in `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,
],
```

Aan de gebruikskant geef je de disknaam op, niet de drivernaam.

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

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

<Info>
  Dit voorbeeld toont alleen het aanmaakpad voor lokale opslag. Het serveren van bestanden via `serve` en het aanbieden van tijdelijke URL's vallen erbuiten. Als een eigen adapter URL-generatie, zichtbaarheid, alleen-lezen en dergelijke ondersteunt, controleer dan elke implementatie en de benodigde afhankelijke packages, en ga er niet van uit dat het doorgeven van een configuratiesleutel volstaat om ze in te schakelen.
</Info>

## Benoemde disks worden na het aanmaken vastgehouden

`disk('reports')` roept de callback niet elke keer aan. De methode `get()` van de Manager geeft voorrang aan de al aangemaakte instantie in de interne array `$disks`. Alleen als de disk nog niet is aangemaakt, wordt `resolve()` doorlopen en wordt het resultaat vastgehouden met de disknaam als sleutel.

```mermaid theme={null}
flowchart TD
    A["boot() van de provider"] --> B["Aanmaakroutine registreren met extend()"]
    B --> C["Storage::disk('reports')"]
    C --> D{"Is reports al aangemaakt?"}
    D -->|Ja| E["Vastgehouden instantie retourneren"]
    D -->|Nee| F["driver lezen en configuratie aan de aanmaakroutine doorgeven"]
    F --> G["Resultaat vasthouden als reports"]
    G --> E
```

Daarom wordt een al aangemaakte disk niet automatisch bijgewerkt als je het volgende in hetzelfde proces doet.

* `filesystems.disks.reports` wijzigen met `config()`.
* `Storage::extend()` opnieuw aanroepen voor dezelfde drivernaam.

`FilesystemServiceProvider` registreert ook de Manager zelf als singleton. Ga er in langlopende processen niet van uit dat disks per request of per job altijd opnieuw worden aangemaakt.

## Na een configuratiewijziging alleen de benodigde disks opnieuw resolven

Als je binnen hetzelfde proces de configuratie wijzigt en controleert, scheid je het bijwerken van de configuratie van het verwijderen van de vastgehouden disk.

```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()` verwijdert de opgegeven naam uit de array met vastgehouden disks van de Manager. De volgende aanroep van `disk()` leest de huidige configuratie opnieuw in. In de gecontroleerde versie verwijdert ook `purge()` alleen de opgegeven naam; het roept geen methode aan om de verbinding van een eigen backend te sluiten.

<Warning>
  Referenties die aan de gebruikskant worden vastgehouden, zoals `$before`, worden daarmee niet herschreven. Hetzelfde geldt als een singleton-service een oude disk vasthoudt. Gebruik `forgetDisk()` niet als mechanisme om alle referenties of andere processen in één keer bij te werken.
</Warning>

Bij configuratiewijzigingen of package-updates in productie maak je de configuratiecache opnieuw aan volgens je gewone deployment en herstart je ook langlopende workers. De configuratiecache en de array met vastgehouden disks binnen dit proces zijn twee verschillende dingen.

### build gebruiken voor tijdelijke configuratie

Als je een benoemde, gedeelde configuratie niet wilt wijzigen, kun je een [on-demand disk](/nl/filesystem) gebruiken.

```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()` roept `resolve()` rechtstreeks aan met de opgegeven configuratie en voegt het resultaat niet toe aan de array met vastgehouden benoemde disks. De aangepaste driver moet nog steeds geregistreerd zijn, maar elke aanroep doorloopt de aanmaakroutine. Ook bij dynamische opslaglocaties ontwerp je het systeem niet zo dat de opslaglocatie of het verbindingsdoel onbeperkt op basis van gebruikersinvoer gekozen kan worden.

## Het aanmaakpad los van fake testen

`Storage::fake('reports')` vervangt die disk via de methode `set()` van de Manager door een lokale testdisk. Dat is handig om bestandsbewerkingen van de applicatie te testen, maar het **controleert niet of de aangepaste aanmaakroutine van het package correct wordt geregistreerd en uitgevoerd**.

Laad `ArchiveServiceProvider` in de [testomgeving van het package](/nl/advanced/package-testing) en controleer daarna de volgende punten afzonderlijk.

| Test | Wat je controleert |
| - | - |
| Normaal opstarten | Als er geen disk wordt gebruikt, starten de configuratievalidatie en bestandsbewerkingen in de aanmaakroutine niet |
| Benoemde disks | `reports` en `exports` krijgen elk hun eigen configuratie en zijn verschillende instanties |
| Dezelfde naam opnieuw ophalen | Twee keer `disk('reports')` aanroepen levert dezelfde instantie op |
| Configuratiewijziging | Alleen de configuratie wijzigen levert dezelfde instantie op; na `forgetDisk()` is het een andere instantie |
| On-demand | Twee keer `build()` aanroepen met dezelfde configuratie levert verschillende instanties op |
| Ongeldige configuratie | In dit voorbeeld leidt het resolven van een disk zonder `root` tot een exception |
| Echt lezen en schrijven | Opslaan, ophalen en verwijderen controleren in een map die alleen voor tests is, en aan het eind opruimen |
| Met configuratiecache | Ook in een vers opgestarte verificatieapplicatie is de driver geregistreerd en kan hij worden geresolved |

Bij een eigen externe backend scheid je aanmaaktests zonder netwerk van verbindingstests in een expliciet voorbereide verificatieomgeving. Beschouw een geslaagde fake niet als bewijs van compatibiliteit met de echte service.

## Checklist voor onderhoud op lange termijn

* Documenteer de drivernaam, configuratiesleutels, de API van de retourwaarde en de afhandeling van exceptions en `throw` als publieke specificatie.
* Gebruik een extensienaam die niet botst met standaarddrivers of andere packages.
* Resolve of gebruik geen disks alleen doordat de provider opstart.
* Maak bij configuratiewijzigingen onderscheid tussen de configuratiecache, de array met vastgehouden disks van de Manager, referenties aan de gebruikskant en andere processen.
* Controleer voor elke ondersteunde Laravel-versie doorlopend het aanmaken, het opnieuw resolven en echte bestandsbewerkingen.

## Geraadpleegde primaire bronnen

* [Officiële Laravel-documentatie: aangepaste bestandssystemen](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: registratie van de Manager als singleton](https://github.com/laravel/framework/blob/v13.37.0/src/Illuminate/Filesystem/FilesystemServiceProvider.php)
* [Storage-facade: vervanging door een lokale disk via fake](https://github.com/laravel/framework/blob/v13.37.0/src/Illuminate/Support/Facades/Storage.php)
* [Officiële Laravel-tests: aanmaken, verwijderen en aangepaste closures van disks](https://github.com/laravel/framework/blob/v13.37.0/tests/Filesystem/FilesystemManagerTest.php)


## Related topics

- [Artisan-commands van een package registreren en afhankelijkheden resolven](/nl/advanced/package-commands.md)
- [Hooks na het resolven van packageservices](/nl/advanced/package-service-resolution.md)
- [Middleware van packages registreren en het toepassingsbereik](/nl/advanced/package-middleware.md)
- [Routes van packages registreren en cachen](/nl/advanced/package-routes.md)
- [Event listeners van een package registreren en cachen](/nl/advanced/package-events.md)


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