
Qualche giorno fa ho deciso di impiegare un po’ di tempo per aggiornare un’applicazione Laravel rimasta ferma per anni.
L’applicazione girava in produzione con:
- Laravel 5.7
- PHP 7.4
Il provider di hosting continuava a ricordarmi che PHP 7.4 era ormai fuori supporto e suggeriva il passaggio a PHP 8, suggerimento che era abbastanza inistente da dentro l’interfaccia di amministrazione di WordPress.
Avrei aggiornato subito senonché una di queste mie app era rimasta indietro con gli aggiornamenti, quindi non mio era possibile aggiornare semplicemente la versione di PHP: Laravel 5.7 non è compatibile con PHP 8. Occorre quindi aggiornare prima il framework.
L’errore da evitare
La tentazione iniziale è quella di modificare il composer.json e passare direttamente all’ultima versione disponibile.
È probabilmente il modo migliore per ritrovarsi davanti a decine di errori contemporaneamente, senza capire quale sia la causa di ciascuno.
Ho preferito una strategia diversa.
Una versione funzionante ad ogni passo
Per prima cosa ho ricreato l’intero ambiente di produzione desiderato in un container Docker.
Questo mi ha permesso di lavorare in completa sicurezza, con una copia fedele dell’applicazione e del database.
Successivamente ho importato tutto in Git e ho creato un branch dedicato per ogni salto di versione:
Laravel 5.7
↓
Laravel 5.8
↓
Laravel 6
↓
Laravel 7
↓
Laravel 8
↓
PHP 8.1
Ad ogni passaggio ho seguito sempre lo stesso schema:
- aggiornamento del
composer.json; composer update;- correzione degli eventuali problemi;
- test dell’applicazione;
- commit;
- tag Git.
In questo modo ogni versione rimaneva perfettamente funzionante e, in qualsiasi momento, era possibile tornare indietro.
Il passaggio più delicato
Contrariamente a quanto immaginavo, il salto più impegnativo non è stato quello verso PHP 8.
Il punto più critico è stato Laravel 7.
Qui ho incontrato alcune modifiche strutturali del framework:
- il passaggio da
ExceptionaThrowablenell’handler delle eccezioni; - l’introduzione del pacchetto
laravel/uiper l’autenticazione; - l’aggiornamento di Collision, Tinker e PHPUnit.
Sono tutti cambiamenti documentati, ma affrontandoli uno alla volta risultano sorprendentemente semplici da risolvere.
Laravel diventa più severo
Una delle cose che apprezzo di più negli aggiornamenti è che il framework diventa progressivamente più rigoroso.
Durante la migrazione è emerso un bug che era presente da anni nel codice applicativo.
Avevo una chiamata di questo tipo:
->orderBy('customer', 'data')
L’intenzione era ordinare prima per cliente e poi per data.
Le versioni precedenti lo lasciavano passare; Laravel 8, invece, segnala correttamente che il secondo parametro di orderBy() deve essere necessariamente "asc" oppure "desc".
La correzione è stata banale:
->orderBy('customer')
->orderBy('data')
Questo è uno dei vantaggi meno evidenti degli aggiornamenti: oltre alla sicurezza e alle nuove funzionalità, aiutano a scoprire errori che erano sempre rimasti nascosti.
Un problema… che non era di Laravel
Durante i test una vista MySQL ha smesso improvvisamente di funzionare.
La causa, però, non era il framework.
La vista era stata importata da un dump e manteneva un DEFINER riferito a un utente inesistente nell’ambiente Docker.
In produzione il problema non esisteva perché quell’utente era ancora presente.
È stato un buon promemoria del fatto che, durante una migrazione, non tutto ciò che si rompe dipende necessariamente dal framework.
Il passaggio finale
Una volta raggiunto Laravel 8, il passaggio a PHP 8.1 è stato sorprendentemente semplice.
È bastato aggiornare l’immagine Docker, verificare le dipendenze e ripetere la batteria di test.
Infine ho predisposto una nuova directory sul server, installato le dipendenze con Composer e sostituito la vecchia applicazione semplicemente rinominando le directory.
Il rollback, se fosse stato necessario, sarebbe consistito in due comandi mv.
Considerazioni finali
Ripensandoci, la lezione più importante di questa esperienza non riguarda Laravel.
Riguarda il metodo.
Docker mi ha consentito di lavorare su una copia fedele della produzione.
Git mi ha permesso di fotografare ogni stato stabile della migrazione.
L’approccio incrementale ha fatto sì che ogni errore avesse una sola causa possibile.
Alla fine della giornata l’applicazione era passata da Laravel 5.7 e PHP 7.4 a Laravel 8.83 e PHP 8.1, senza tempi di fermo significativi e con un percorso completamente tracciabile.
Spesso gli upgrade fanno paura perché si immaginano come un salto nel vuoto.
In realtà, affrontati un passo alla volta, sono molto meno traumatici di quanto si possa pensare.
Il ruolo dell’AI
Naturalmente mi sono fatto aiutare dall’AI.
L’intero lavoro, documentazione compresa, ha richiesto circa sei ore: un tempo che, realisticamente, sarebbe stato molto più lungo se avessi dovuto consultare manualmente documentazione, forum e guide per ogni singolo problema.
L’aspetto che mi ha colpito di più, però, è un altro.
La strategia della migrazione è rimasta sempre nelle mie mani: ho deciso di procedere per passi successivi, ricreando l’ambiente con Docker, utilizzando Git per fotografare ogni stato stabile e affrontando una major release alla volta.
L’AI ha svolto il ruolo di un collega competente: suggeriva soluzioni, aiutava a interpretare gli errori, richiamava la documentazione pertinente e proponeva miglioramenti al processo. Ogni scelta importante, però, è stata verificata e compresa prima di essere applicata.
È probabilmente questo il modo di lavorare con l’AI che trovo più produttivo: non sostituisce la comprensione del problema, ma riduce drasticamente il tempo necessario per arrivare alla soluzione.








Commenti recenti