Introduzione
Laravel 13 è stato rilasciato a marzo 2026. Questa guida illustra la procedura di aggiornamento da Laravel 12.x a 13.x.Il tempo stimato necessario all’aggiornamento è di circa 10 minuti. L’impatto dei breaking change sull’applicazione varia in base a dimensione e funzionalità usate.
Aggiornamento assistito dall’AI
Puoi automatizzare l’aggiornamento con Laravel Boost. Boost è un server MCP di prima parte che fornisce agli assistenti AI prompt di aggiornamento passo passo. Installalo nell’app Laravel 12 e usa lo slash command/upgrade-laravel-v13 con Claude Code, Cursor, OpenCode, Gemini o VS Code per avviare l’aggiornamento a Laravel 13. Il comando richiede laravel/boost ^2.0.
Anche con strumenti AI che non supportano gli slash command puoi eseguire la stessa procedura di aggiornamento referenziando direttamente il file di prompt. Incolla nell’AI il prompt seguente così com’è.
prompt
Cambiamenti per livello di impatto
Impatto: Alto
- Aggiornamento delle dipendenze
- Aggiornamento dell’installer di Laravel
- Protezione anti-forgery delle richieste (CSRF)
Impatto: Medio
- Configurazione
serializable_classesdella cache - Configurazione
serializationdella sessione
Impatto: Basso
- Prefisso della cache e nome del cookie di sessione
- Serializzazione dei modelli in collection
Container::calle default di classi nullable- Priorità di registrazione delle rotte con dominio
- Payload dell’eccezione dell’evento
JobAttempted - Binding delle callback di
extenddel Manager - Query MySQL
DELETE(JOIN / ORDER BY / LIMIT) - Nomi delle view di paginazione Bootstrap
- Generazione dei nomi delle tabelle pivot polimorfiche
- Rinomina di una proprietà dell’evento
QueueBusy - Reset della factory
Strtra test
Procedura di aggiornamento
Aggiornamento delle dipendenze
Impatto: Alto Aggiorna incomposer.json le seguenti dipendenze.
Aggiornamento dell’installer di Laravel
Impatto: Alto Se usi la CLI dell’installer di Laravel per creare nuove app, aggiornalo a una versione compatibile con Laravel 13.x. Se l’hai installato concomposer global require:
Modifiche non retrocompatibili (Breaking Changes)
Sicurezza
Protezione anti-forgery delle richieste
Impatto: Alto Il middleware CSRF di Laravel è stato rinominato daVerifyCsrfToken a PreventRequestForgery. È stata aggiunta anche la verifica dell’origine della richiesta tramite l’header Sec-Fetch-Site.
VerifyCsrfToken e ValidateCsrfToken restano come alias deprecati, ma tutti i riferimenti diretti vanno aggiornati a PreventRequestForgery. Occorre particolare attenzione nei punti in cui il middleware viene escluso, come test e definizioni di rotta.
preventRequestForgery(...).
Cache
Prefisso della cache e nome del cookie di sessione
Impatto: Basso Il prefisso predefinito delle chiavi di cache e Redis usa ora un suffisso separato da trattino. Il nome del cookie di sessione predefinito usa oraStr::snake(...).
Molte applicazioni impostano valori espliciti nei file di configurazione e quindi non risentono di questa modifica. Sono interessate solo le app che si affidano ai fallback del framework.
.env.
Configurazione serializable_classes della cache
Impatto: Medio
Alla configurazione predefinita di cache è stata aggiunta l’opzione serializable_classes, con default false. Serve a prevenire attacchi di deserializzazione PHP tramite gadget chain in caso di compromissione di APP_KEY.
Se la tua app salva intenzionalmente oggetti PHP in cache, devi elencare esplicitamente le classi ammesse alla deserializzazione.
Configurazione serialization della sessione
Impatto: Medio
Nello scheletro di Laravel 13 (laravel/laravel), a config/session.php è stato aggiunto 'serialization' => 'json'. Tuttavia, il default interno del framework rimane php.
La guida ufficiale di aggiornamento non riporta questa modifica. Va intesa come “non è necessario modificarla”. In Laravel a volte, per aggiornamenti dall’ultima major, alcune modifiche non compaiono nella guida di aggiornamento perché non hanno impatto. Quando dovrai aggiornare tra qualche anno, ti serviranno queste informazioni: registrarle in modo non ufficiale è importante.
Per mantenere il comportamento delle versioni precedenti a Laravel 12, imposta esplicitamente 'serialization' => 'php'.
Container
Container::call e default di classi nullable
Impatto: Basso
Container::call rispetta ora i valori di default dei parametri di classe nullable quando il binding non esiste (in linea con il comportamento introdotto in Laravel 12 per la constructor injection).
Database
Query MySQL DELETE
Impatto: Basso
Laravel compila ora, nella grammatica MySQL, DELETE ... JOIN completi che includono ORDER BY e LIMIT.
Nelle versioni precedenti, in un DELETE con JOIN le clausole ORDER BY / LIMIT potevano essere ignorate. In Laravel 13 queste clausole sono incluse nell’SQL generato. Di conseguenza, alcuni engine di database che non supportano questa sintassi possono generare QueryException.
Eloquent
Generazione dei nomi delle tabelle pivot polimorfiche
Impatto: Basso Quando viene stimato il nome della tabella di modelli pivot polimorfici che usano una classe pivot personalizzata, Laravel genera ora nomi al plurale. Se dipendevi dal precedente nome stimato al singolare, dichiara esplicitamente il nome della tabella nel modello pivot.Serializzazione dei modelli in collection
Impatto: Basso Quando una collection di modelli Eloquent viene serializzata e ripristinata (per esempio, in un job in coda), le relazioni eager-loaded vengono ora ripristinate per i modelli. Se il tuo codice si aspettava che dopo la deserializzazione le relazioni non esistessero, va corretto.Code
Payload dell’eccezione dell’evento JobAttempted
Impatto: Basso
L’evento Illuminate\Queue\Events\JobAttempted espone ora, al posto della precedente proprietà boolean $exceptionOccurred, un oggetto eccezione (o null) nella proprietà $exception.
Rinomina di una proprietà dell’evento QueueBusy
Impatto: Basso
Nell’evento Illuminate\Queue\Events\QueueBusy, la proprietà $connection è stata rinominata in $connectionName per coerenza con altri eventi di coda.
Routing
Priorità di registrazione delle rotte con dominio
Impatto: Basso Le rotte con un dominio esplicito hanno ora priorità sulle rotte senza dominio nella matching delle rotte. In questo modo le rotte catch-all su sottodominio funzionano in modo coerente anche se le rotte senza dominio sono registrate prima.Support
Binding delle callback di extend del Manager
Impatto: Basso
Le closure dei driver personalizzati registrate con il metodo extend del Manager vengono ora bindate all’istanza del manager.
Se in queste callback usavi $this riferendoti a un altro oggetto (ad esempio l’istanza del service provider), devi spostare il valore nella closure con use (...).
Reset della factory Str tra test
Impatto: Basso
Laravel resetta ora le factory personalizzate Str nel teardown dei test.
Se dipendevi dal fatto che le factory personalizzate di UUID / ULID / stringhe casuali persistessero tra i metodi di test, impostale in ciascun test o in un setup hook.
View
Nomi delle view di paginazione Bootstrap
Impatto: Basso I nomi interni delle view di paginazione predefinite di Bootstrap 3 sono diventati espliciti.Funzionalità deprecate
| Funzionalità | Alternativa |
|---|---|
Middleware VerifyCsrfToken | PreventRequestForgery |
Middleware ValidateCsrfToken | PreventRequestForgery |
JobAttempted::$exceptionOccurred | JobAttempted::$exception |
QueueBusy::$connection | QueueBusy::$connectionName |
Aggiunte ai contract
Impatto: Molto basso Rilevante solo se hai implementazioni personalizzate.Contract Dispatcher
Al contract Illuminate\Contracts\Bus\Dispatcher è stato aggiunto il metodo dispatchAfterResponse($command, $handler = null).
Contract ResponseFactory
Al contract Illuminate\Contracts\Routing\ResponseFactory è stata aggiunta la firma di eventStream.
Contract MustVerifyEmail
Al contract Illuminate\Contracts\Auth\MustVerifyEmail è stato aggiunto markEmailAsUnverified().
Contract Queue
Al contract Illuminate\Contracts\Queue\Queue sono stati aggiunti i seguenti metodi di ispezione delle dimensioni della coda (prima erano dichiarati solo tramite docblock).
pendingSizedelayedSizereservedSizecreationTimeOfOldestPendingJob
Contract Store / Repository
Ai contract di cache è stato aggiunto il metodo touch per l’estensione del TTL.
Punti salienti delle nuove funzionalità
Aggiornamento assistito dall’AI (Laravel Boost)
Laravel Boost è il server MCP ufficiale. Si integra con editor AI e permette di semi-automatizzare l’aggiornamento con il comando/upgrade-laravel-v13.
Verifica dell’origine tramite header Sec-Fetch-Site
Il middleware PreventRequestForgery effettua una verifica aggiuntiva dell’origine tramite l’header Sec-Fetch-Site. Ciò rafforza la protezione CSRF.
Deserializzazione sicura della cache
Grazie alla configurazioneserializable_classes vengono deserializzate solo le classi consentite. Migliora la sicurezza contro gli attacchi di deserializzazione PHP.
eventStream per SSE (Server-Sent Events)
Al contract ResponseFactory è stato aggiunto eventStream, migliorando il supporto a Server-Sent Events.
Migliore visibilità delle code
I metodipendingSize, delayedSize e reservedSize del contract Queue permettono un monitoraggio più fine dello stato della coda.
Problemi comuni nella migrazione e soluzioni
Problema: i test CSRF falliscono
Sintomo: i test che referenzianoVerifyCsrfToken falliscono con errore di classe non trovata.
Soluzione: aggiorna tutti i riferimenti a PreventRequestForgery.
Problema: non si riesce a ripristinare oggetti dalla cache
Sintomo: i dati recuperati dalla cache sononull oppure viene sollevata UnserializationFailedException.
Soluzione: aggiungi le classi usate a serializable_classes in config/cache.php oppure converti in array i valori da cachare.
Problema: il listener JobAttempted non funziona
Sintomo: $event->exceptionOccurred è null o dà errore di proprietà indefinita.
Soluzione: cambia in $event->exception !== null.
Problema: le sessioni vengono invalidate
Sintomo: dopo l’aggiornamento gli utenti vengono sloggati. Soluzione: il nome del cookie di sessione predefinito è cambiato. Imposta esplicitamenteSESSION_COOKIE in .env per mantenere il valore precedente.
Problema: chiavi di cache non trovate
Sintomo: dopo l’aggiornamento aumentano i cache miss. Soluzione: il prefisso della cache è cambiato. ImpostaCACHE_PREFIX in .env o svuota la cache.
Riferimenti
- Guida ufficiale all’aggiornamento (in inglese)
- Diff del repository laravel/laravel (12.x → 13.x)
- Laravel Shift — servizio della community che automatizza l’aggiornamento
- Laravel Boost — server MCP per aggiornamenti assistiti dall’AI