Un’applicazione Laravel scritta qualche anno fa e poi lasciata ferma accumula ritardo in fretta. Laravel pubblica una versione principale all’anno, e ciascuna riceve correzioni di sicurezza per due anni. Chi è rimasto su Laravel 5, 6 o 8 si trova quindi diverse versioni indietro, con un framework senza patch, un PHP spesso fuori supporto e pacchetti che nel frattempo hanno cambiato nome, interfaccia o manutentore.
La tentazione è saltare direttamente all’ultima versione. Quasi sempre è la strada più lunga. In questo articolo descriviamo la strategia che usiamo per aggiornare Laravel di più versioni principali: una alla volta, alternando gli aggiornamenti del framework e quelli di PHP, con i test a fare da rete di sicurezza e le dipendenze affrontate prima del codice.
Il ciclo di vita di Laravel
Secondo la politica di supporto ufficiale, ogni versione principale di Laravel riceve correzioni di bug per 18 mesi e correzioni di sicurezza per 2 anni. Ogni versione richiede anche una versione minima di PHP, e la soglia sale quasi a ogni rilascio. La tabella riassume le versioni che incontriamo più spesso nei progetti da aggiornare.
| Laravel | Uscita | PHP supportato | Stato a ottobre 2026 |
|---|---|---|---|
| 5.5 (LTS) | agosto 2017 | 7.0 o superiore | fuori supporto da agosto 2020 |
| 5.8 | febbraio 2019 | 7.1.3 o superiore | fuori supporto da febbraio 2020 |
| 6 (LTS) | settembre 2019 | 7.2 – 8.0 | fuori supporto da settembre 2022 |
| 7 | marzo 2020 | 7.2.5 – 8.0 | fuori supporto da marzo 2021 |
| 8 | settembre 2020 | 7.3 – 8.1 | fuori supporto da gennaio 2023 |
| 9 | febbraio 2022 | 8.0 – 8.2 | fuori supporto da febbraio 2024 |
| 10 | febbraio 2023 | 8.1 – 8.3 | fuori supporto da febbraio 2025 |
| 11 | marzo 2024 | 8.2 – 8.4 | fuori supporto da marzo 2026 |
| 12 | febbraio 2025 | 8.2 – 8.5 | solo sicurezza fino al 24 febbraio 2027 |
| 13 | marzo 2026 | 8.3 – 8.5 | supporto attivo, sicurezza fino al 17 marzo 2028 |
A ottobre 2026 solo Laravel 12 e 13 ricevono ancora correzioni, e Laravel 12 è già in sola sicurezza. Un’applicazione su una versione precedente non riceve patch per il framework, e quasi sempre gira anche su un PHP fuori supporto, perché le versioni vecchie di Laravel non sono compatibili con i rami di PHP più recenti.
Perché una versione principale alla volta
Laravel pubblica una guida di aggiornamento per ogni passaggio, dalla versione precedente a quella nuova: da 9 a 10, da 10 a 11 e così via. Non esistono guide da 6 a 13. Saltare più versioni significa applicare insieme le modifiche di tutte le guide intermedie, senza poter capire quale di queste ha rotto un test o una pagina.
Procedendo un passo alla volta, invece, ogni aggiornamento è piccolo e verificabile: si aggiornano le dipendenze indicate dalla guida, si applicano le modifiche, si lanciano i test, si corregge e si passa al successivo. Le guide stimano tempi brevi per un’applicazione standard, da pochi minuti a un’ora per passaggio. Un’applicazione reale, con molti pacchetti e personalizzazioni, richiede di più, ma il lavoro resta diviso in unità che si possono pianificare e rilasciare.
L’ordine: Laravel e PHP a passi alternati
Ogni versione di Laravel supporta un intervallo di versioni di PHP, e intervalli consecutivi si sovrappongono. Questa sovrapposizione definisce l’ordine di lavoro: si aggiorna Laravel finché la versione di PHP in uso lo consente, poi si aggiorna PHP restando sulla stessa versione di Laravel, poi di nuovo Laravel. Un esempio, partendo da Laravel 6 su PHP 7.2:
- Laravel 7, che richiede almeno PHP 7.2.5;
- PHP 7.3 restando su Laravel 7, poi Laravel 8;
- PHP 8.0 restando su Laravel 8, poi Laravel 9;
- PHP 8.1 restando su Laravel 9, poi Laravel 10;
- PHP 8.2 o 8.3 restando su Laravel 10, poi Laravel 11 e 12;
- Laravel 13, che richiede PHP 8.3, e più avanti PHP 8.4 o 8.5.
Il passaggio da PHP 7.x a 8.0 è quello che porta più sorprese, perché oltre al framework cambia il comportamento del linguaggio stesso. Lo descriviamo nell’articolo sulle funzioni rimosse in PHP 8. Conviene farlo su una versione di Laravel che si conosce bene, separato da qualunque altro aggiornamento.
Prima di cominciare: i test
Una serie di aggiornamenti consecutivi senza test è una scommessa ripetuta a ogni versione. Molte applicazioni Laravel legacy hanno pochi test o nessuno: prima di toccare il framework conviene scriverne almeno sui percorsi che contano per l’azienda. Non servono test raffinati. Bastano test HTTP che aprono le pagine principali, eseguono un login, inviano i form più importanti e controllano lo stato della risposta e qualche dato nel database.
- le rotte pubbliche più visitate e quelle che generano fatturato, come carrello, checkout e area riservata;
- le API usate da applicazioni esterne, con il formato esatto delle risposte;
- i comandi pianificati e le code, che si rompono in silenzio;
- le email e le notifiche, verificate con i fake di Laravel invece che con invii reali.
Anche l’analisi statica aiuta molto, perché trova chiamate a metodi rimossi senza dover eseguire ogni percorso. Ne parliamo nell’articolo su PHPCompatibility, PHPStan e Rector.
Le dipendenze, il vero collo di bottiglia
Il framework si aggiorna seguendo la guida. Il problema sono i pacchetti di terze parti: ciascuno deve avere una versione compatibile con la nuova versione di Laravel, e alcuni nel frattempo sono stati abbandonati. Prima di ogni passaggio conviene sapere quali pacchetti lo bloccano:
# Pacchetti installati direttamente e versioni più recenti disponibili
composer outdated --direct
# Quali pacchetti impediscono di installare Laravel 10
composer why-not laravel/framework 10.0
# Dopo aver aggiornato composer.json come indicato dalla guida di upgrade
composer update --with-all-dependencies
# Test (su Laravel 6 si usa vendor/bin/phpunit)
php artisan test
Per ogni pacchetto bloccante le strade sono tre: aggiornarlo, sostituirlo con un equivalente mantenuto, oppure eliminarlo riscrivendo la piccola parte di funzionalità che l’applicazione usava davvero. Un pacchetto abbandonato fermo su una vecchia versione di Laravel blocca tutto il percorso, e va affrontato all’inizio.
Lo stesso vale per i pacchetti ufficiali di Laravel. Ogni guida indica le versioni richieste di pacchetti come Sanctum, Passport, Cashier e Telescope, che hanno a loro volta una propria guida di aggiornamento. Con Laravel 11, per esempio, Sanctum deve passare alla versione 4 e Passport alla 12, e questi pacchetti non caricano più in automatico le proprie migrazioni del database: vanno pubblicate nell’applicazione con il comando php artisan vendor:publish indicato dalla guida, prima di lanciare le migrazioni in produzione.
Il ciclo per ogni versione
Ogni passaggio segue lo stesso ciclo, su un ramo dedicato del repository:
Le guide classificano ogni modifica per probabilità di impatto, alta, media o bassa. Le modifiche ad alto impatto vanno lette tutte; quelle a impatto basso si verificano cercando nel codice le classi e i metodi citati. Conviene anche confrontare i file di configurazione con quelli dello scheletro laravel/laravel della nuova versione, che le guide stesse indicano come riferimento.
I passaggi che richiedono più attenzione
Ogni guida ha le sue sorprese. Questi sono i punti che, nella nostra esperienza, chiedono più tempo:
- Laravel 6: gli helper globali per stringhe e array, come
str_slug()earray_get(), escono dal framework. Si sostituiscono conStreArro con il pacchettolaravel/helpers; - Laravel 8: le factory dei modelli diventano classi, e quelle scritte nello stile precedente funzionano solo con il pacchetto
laravel/legacy-factories; - Laravel 9: richiede PHP 8.0.2, sostituisce SwiftMailer con Symfony Mailer e passa a Flysystem 3, che cambia il comportamento di scrittura e lettura dei file;
- Laravel 11: introduce una struttura dell’applicazione più snella, che però la guida sconsiglia di adottare per le applicazioni aggiornate da Laravel 10. Cambiano invece le migrazioni che modificano colonne, che devono ripetere tutti gli attributi da conservare;
- Laravel 13: richiede PHP 8.3 e rinomina il middleware CSRF in
PreventRequestForgery.
Le guide citano anche Laravel Shift, un servizio mantenuto dalla comunità che automatizza buona parte delle modifiche. Può far risparmiare tempo sulle parti meccaniche; la revisione del risultato e i test restano comunque necessari.
Rilascio e produzione
Non è obbligatorio rilasciare in produzione ogni versione intermedia. Conviene però farlo almeno nei punti in cui cambia PHP, perché il server va comunque aggiornato e un rilascio intermedio riduce la quantità di modifiche che arrivano insieme in produzione. Ogni rilascio ha bisogno di un ambiente di prova con la stessa versione di PHP, le stesse estensioni e una copia recente dei dati, e di un piano di rollback che includa le migrazioni del database.
Se il percorso è lungo e la produzione gira su un PHP già fuori supporto, il server va protetto per tutta la durata del progetto. È il caso tipico in cui affianchiamo alla migrazione applicativa il backport delle patch di sicurezza sul PHP in uso, fino al rilascio sulla versione supportata.
Riassumendo
Ogni versione principale di Laravel riceve correzioni di sicurezza per due anni, e a ottobre 2026 sono supportate solo la 12, in sola sicurezza fino a febbraio 2027, e la 13, che richiede PHP 8.3. Per aggiornare un’applicazione rimasta indietro di più versioni conviene procedere una versione alla volta, seguendo la guida ufficiale di ogni passaggio e alternando gli aggiornamenti di Laravel e di PHP negli intervalli in cui si sovrappongono. Prima di iniziare servono test sui percorsi critici e un’analisi delle dipendenze, perché i pacchetti di terze parti sono quasi sempre il vero collo di bottiglia. Ogni passaggio segue lo stesso ciclo, su un ramo dedicato, e i rilasci intermedi vanno almeno nei punti in cui cambia PHP, con la produzione protetta fino all’arrivo sulla versione supportata.