Cache::extend() è il modo di creare lo store: Laravel non avvolge automaticamente in un Repository lo Store che restituisci.
Questa pagina esamina l’implementazione di Laravel Framework v13.39.0. Per le operazioni di base consulta Cache, per la preparazione del provider consulta Sviluppo di pacchetti.
Separare il nome del driver dal nome dello store
Se esiste una callback di creazione personalizzata corrispondente al
driver della configurazione, CacheManager::build() la invoca prima dei driver integrati. Non riutilizzare nomi come redis o array: usa un nome specifico del pacchetto.
Registrare prima del boot degli altri provider
Se un altro pacchetto usa la cache nel proprioboot(), registrare il driver nel tuo boot() potrebbe non arrivare in tempo, a seconda dell’ordine. Seguendo la documentazione ufficiale, in register() registra una callback booting dell’applicazione.
L’esempio seguente è minimo e usa l’ArrayStore standard per verificare il percorso di registrazione senza servizi esterni. Collocalo in src/MemoServiceProvider.php del pacchetto Acme\Memo.
- Nel normale avvio, la callback
bootingdell’applicazione viene eseguita dopo il completamento diregister()di tutti i provider e prima di ciascunboot(). È diversa da$this->booting()del provider stesso. - Alla callback di
extend()vengono passati l’applicazione e l’array di configurazione dello store. Colloca la creazione dello Store e le connessioni esterne in questa callback di creazione. - Questo momento di registrazione non garantisce il funzionamento per l’uso della cache all’interno di
register()di altri provider. Separa la registrazione dei servizi dal loro utilizzo effettivo.
CacheManager::extend() ricollega lo scope delle closure anonime al Manager. Non considerare $this di una closure non static come il provider: come nell’esempio, usa closure static e l’argomento $app.
Aggiungere lo store nell’applicazione che usa il pacchetto
Aggiungilo all’arraystores esistente in config/cache.php. Non progettare il pacchetto in modo che sovrascriva il default o l’intero stores dell’applicazione.
CACHE_STORE indichi il nome dello store catalog, non il nome del driver. Se crei più configurazioni con lo stesso driver, viene generato un Repository distinto per ogni nome di store.
Costruire il Repository da sé
CacheManager::callCustomCreator() restituisce così com’è il valore restituito dalla callback. Se restituisci solo lo Store, anche se get() e put() funzionano, metodi del Repository come remember() non sono disponibili e anche l’interpretazione del TTL cambia.
Nell’esempio, repository($store, $config) si occupa di quanto segue.
- Avvolge lo Store con
Illuminate\Cache\Repository. - Passa al Repository il nome
storeche il Manager ha aggiunto alla configurazione. - Se è registrato un Dispatcher di eventi e l’opzione
eventsnon è disabilitata, imposta il Dispatcher sul Repository.
serialize, letto dalla configurazione nell’esempio.
Confrontare il contratto Store con l’implementazione attuale
Implementa i metodi richiesti daIlluminate\Contracts\Cache\Store in Laravel 13. Non distribuire come driver funzionante un elenco di metodi vuoti preso da esempi passati.
Il Repository tratta
null come cache miss. L’implementazione non deve trattare come mancanti anche false o 0. Salvare null non funziona come marcatore per evitare il ricalcolo di remember().
Verificare il TTL passando per il Repository
Repository::put() elabora il TTL prima di passarlo allo Store.
Verificare separatamente il supporto ad add, lock e tag
La sola implementazione del contratto Store non garantisce il supporto a tutte le funzionalità della cache.add()atomico: non fa parte del contratto Store. Quando viene chiamato con un TTL positivo e lo Store haadd(), il Repository lo usa. Altrimenti ricorre a un fallback conget()eput(), quindi il solo wrapping nel Repository non garantisce l’atomicità. Con un backend condiviso, implementalo con un’operazione atomica di quel backend e verifica anche l’esecuzione concorrente.- Lock:
lock()erestoreLock()diIlluminate\Contracts\Cache\LockProvidersono un contratto separato. Verifica acquisizione, corrispondenza del proprietario, scadenza e il fatto che non venga rilasciato il lock di un altro proprietario. I lock diArrayStoredell’esempio non forniscono mutua esclusione tra processi diversi. - Tag: il Repository controlla se lo Store ha
tags(). In generale serve un’implementazione basata suTaggableStoreo simili: il contratto Store da solo non li abilita automaticamente.
flush() come una cancellazione parziale che rispetta il prefix della configurazione. Verifica l’ambito della cancellazione sul backend condiviso e spiegalo agli utenti, incluso php artisan cache:clear.
Distinguere la conservazione delle istanze dalla cancellazione dei dati
CacheManager è un singleton e conserva anche il risultato di store('catalog') per ogni nome di store. La sola modifica della configurazione o una nuova registrazione con extend() non aggiorna i Repository già creati.
$same è lo stesso oggetto di $before. Con il recupero successivo a forgetDriver(), $after viene creato dalla nuova configurazione.
forgetDriver() non cancella tutto il backend. Tuttavia, poiché l’ArrayStore dell’esempio conserva i dati all’interno dell’istanza, i vecchi dati non sono visibili dal nuovo Store. Inoltre, i riferimenti al vecchio Repository conservati da $before lato chiamante o dal singleton cache.store già risolto non vengono sostituiti.
In produzione, aggiorna la cache della configurazione seguendo il normale deploy e riavvia i worker di lunga durata. Tieni conto anche del ciclo di vita dei servizi e non trattare una nuova risoluzione come un aggiornamento simultaneo di tutti i processi.
Testare il percorso di creazione, non solo il mock della facade
Nell’ambiente di test dei pacchetti, passa per il Manager e il Repository reali. Il seguente esempio con Testbench verifica che il driver sia utilizzabile anche nelboot() di un altro provider registrato prima. Nell’esempio si salva un array senza modificare la restrizione di deserializzazione cache.serializable_classes e si controlla anche il valore grezzo salvato con ArrayStore::all(false).
many(), l’andata e ritorno di false e 0, touch(), i guasti di connessione, gli aggiornamenti concorrenti, il prefix e l’ambito della cancellazione. Il semplice successo di Cache::shouldReceive('get') non è una prova della registrazione del driver né della compatibilità con il servizio esterno.
Checklist per la manutenzione a lungo termine
- Rendi parte della specifica pubblica il nome del driver, la configurazione dello store, il formato di serializzazione, le eccezioni e i valori restituiti in caso di fallimento.
- Verifica i metodi del contratto Store e le funzionalità opzionali come tag e lock per ogni versione di Laravel supportata.
- Verifica che il driver venga registrato anche in un avvio pulito con la cache della configurazione attiva e che sia utilizzabile dal
boot()di altri provider. - Quando modifichi la compatibilità dei dati salvati, comunicalo includendo la strategia di migrazione o eliminazione delle chiavi esistenti.
- Distingui la conservazione delle istanze nel processo, i dati del backend e la cache della configurazione.
Fonti primarie consultate
- Documentazione ufficiale di Laravel: driver di cache personalizzati
- CacheManager: build, repository, extend, forgetDriver
- Repository: conversione del TTL, add, tags, eventi
- Contratto Store / Contratto LockProvider
- ArrayStore: salvataggio, scadenza, serializzazione
- CacheServiceProvider: registrazione singleton del Manager e di cache.store
- Application: booting dell’applicazione e boot dei provider
- Test ufficiali di Laravel: CacheManagerTest / CacheRepositoryTest