Skip to main content

Cos’è la cache

Le interrogazioni al database e le chiamate ad API esterne hanno un alto costo in CPU e rete e possono impiegare diversi secondi. Se recuperi ripetutamente gli stessi dati, salvare il risultato in cache ti permette di gestire le richieste successive molto più velocemente. Laravel offre un’API unificata compatibile con vari backend di cache: Memcached, Redis, DynamoDB, database e altri.
Di default è configurato il driver database. Passando a Redis o Memcached ottieni una cache ancora più veloce.

Configurazione della cache

config/cache.php

Le impostazioni di cache sono concentrate in config/cache.php. Cambia il driver predefinito con la variabile d’ambiente CACHE_STORE.

Driver disponibili

Salva i dati serializzati in una tabella del database. Dai nuovi progetti Laravel 11 in poi la migration è già inclusa.
Se la migration non è inclusa, creala con Artisan.
Salva i dati di cache sul filesystem. Non richiede setup aggiuntivo, adatto per applicazioni piccole.
Driver di cache veloce, in-memory. Il più usato in produzione. Serve l’estensione PHP PhpRedis o il pacchetto predis/predis.
Serve il pacchetto PECL Memcached. Configura i server in config/cache.php.
Usa AWS DynamoDB come cache store. Crea prima la tabella DynamoDB e installa l’AWS SDK.
Usa un qualsiasi disco filesystem come cache store chiave/valore. Utile per riutilizzare un disco S3 esistente come cache.
array è una cache in-memory valida solo per la richiesta corrente. null ignora ogni operazione. Entrambi utili nei test automatizzati.

Gerarchia dei driver

Usa i driver in base allo scopo e alla velocità.

Operazioni di base

Ottenere la facade Cache

Usa la facade Cache per manipolare la cache.
Per usare più store distinti usa store().

Lettura: Cache::get()

get() legge un dato dalla cache. Se manca restituisce null. Puoi indicare un valore predefinito.

Scrittura: Cache::put()

put() salva un dato. Il terzo argomento è la validità in secondi.
Con add() salvi solo se la chiave non esiste (operazione atomica).
Per salvare in modo permanente usa forever().

Leggi o salva: Cache::remember()

L’operazione più usata. Se la chiave è in cache, restituisce quel valore; altrimenti esegue la closure e salva il risultato.
Con Cache::remember() scrivi i tre passaggi “controlla cache → altrimenti calcola → salva in cache” in una sola riga. Ideale per query DB e risposte API.

Flusso di remember()

Esiste anche rememberForever() senza scadenza.
Se vuoi sapere se il valore proviene dalla cache o è stato appena calcolato, usa rememberWithWarmth(). Restituisce un array con il valore e un booleano che indica se era “caldo” (cache hit).
rememberWithWarmth() è utile per monitorare l’efficienza della cache. Se $warm è spesso false, valuta di aumentare il TTL.

Stale While Revalidate (aggiornamento flessibile della cache)

Con Cache::flexible() indichi in un array il periodo “fresco” e il periodo “utilizzabile anche se vecchio”. Restituisce i dati vecchi all’utente aggiornando la cache in background.

Verifica dell’esistenza: Cache::has()

Increment / decrement

Manipola valori interi.

Leggi ed elimina: Cache::pull()

Recupera il valore e lo elimina. Utile per dati usa-e-getta.

Eliminazione: Cache::forget()

Cache::flush() elimina tutte le voci indipendentemente dal “prefisso” impostato. Attenzione se la cache è condivisa tra più applicazioni.
Con Cache::flushLocks() elimini tutti i lock atomici.

Estensione TTL: Cache::touch()

Estende la scadenza di una voce esistente.

Memoization della cache

Il driver memo mantiene in memoria l’accesso alla cache durante la stessa richiesta. Utile quando accedi ripetutamente alla stessa chiave per ridurre i round trip verso lo store.

Tag della cache

Raggruppa voci correlate con dei tag ed eliminale in blocco.
I tag di cache non sono disponibili con i driver file, dynamodb, database e storage. Servono redis o memcached.

Struttura della cache con tag

Le voci taggate con più tag possono essere eliminate tramite uno qualunque dei tag.

Salvataggio e lettura

Cancellazione

I tag sono utili per invalidare gruppi (per utente, per articolo, ecc.). Es.: Cache::tags(['user', "user:{$userId}"])->flush() per svuotare la cache di uno specifico utente.

Operazioni atomiche (lock)

Con Cache::lock() implementi lock distribuiti per evitare race condition tra processi o richieste concorrenti.
Disponibile con i driver memcached, redis, dynamodb, database, file e array. Tutti i server devono comunicare con lo stesso cache server centrale.

Lock di base

Passando una closure il lock viene rilasciato automaticamente al termine.

Attesa del lock

Attende al massimo i secondi indicati per ottenere il lock. Al timeout viene lanciata LockTimeoutException.
Con closure è più conciso.

Prevenzione dell’esecuzione sovrapposta: withoutOverlapping()

Modo semplice per evitare esecuzioni multiple della stessa logica.

Limitazione della concorrenza: funnel()

Limita quanti processi possono girare in parallelo.

Passaggio del lock tra processi

Ottieni il lock in una richiesta web e lo rilasci in un job in coda.
Per forzare il rilascio indipendentemente dall’owner corrente usa forceRelease.

Rinnovo del lock

Per estendere la scadenza del lock in tuo possesso usa refresh. Senza argomenti usa la durata originale. Utile per elaborazioni lunghe con lock brevi che vuoi rinnovare periodicamente.

Helper cache

L’helper cache() fa le stesse cose della facade in modo più conciso.

Esempi pratici

Cache dei risultati di query

1

Cache dei risultati nel controller

2

Invalidare la cache all'aggiornamento

Cache di modelli Eloquent

Cache di risposte API

Gestione a gruppi con i tag

  • Sviluppo/piccole app: file o database
  • Produzione/alto traffico: redis (con Laravel Horizon anche il monitoraggio è facile)
  • Ambienti AWS: dynamodb o storage (per riutilizzare S3)
  • Test: array o null
  • Naming univoco delle chiavi in tutta l’app (es. users:1:profile)
  • Invalida la cache con Cache::forget() o Cache::tags()->flush() quando i dati cambiano
  • Adatta il TTL alla frequenza di aggiornamento (né troppo breve né troppo lungo)
  • Con Cache::remember() gestisci i miss in modo conciso
  • In produzione usa Redis e valuta il failover
Ultima modifica il 13 luglio 2026