Refactoring applicazione Laravel 10: guida passo-passo per adottare la struttura snella di Laravel 12 e centralizzare la configurazione

Refactoring applicazione Laravel 10: guida passo-passo per adottare la struttura snella di Laravel 12 e centralizzare la configurazione

In un progetto per un'azienda del settore servizi digitali, l'applicativo Laravel 10 che gestiva il backend di una piattaforma SaaS aveva accumulato nel tempo una configurazione frammentata tra sei file: Http/Kernel.php con 14 middleware custom, Console/Kernel.php con 8 task schedulati, RouteServiceProvider con rate limiter personalizzati, AuthServiceProvider con 12 policy registrate manualmente, EventServiceProvider con 20 listener, e un AppServiceProvider che era diventato un contenitore di logica di bootstrap non categorizzabile. L'aggiornamento a Laravel 12 ha funzionato senza toccare la struttura - Laravel 12 supporta pienamente l'architettura di Laravel 10 - ma la migrazione volontaria alla struttura slim introdotta con Laravel 11 ha ridotto quei sei file a uno solo (bootstrap/app.php) più AppServiceProvider, eliminando circa 400 righe di boilerplate.

È necessario adottare la struttura slim quando si aggiorna da Laravel 10?

No. La guida di upgrade a Laravel 12 conferma esplicitamente che l'architettura applicativa di Laravel 10 è pienamente supportata: Http/Kernel.php, Console/Kernel.php e i Service Provider continuano a funzionare senza modifiche. Laravel 12, rilasciato il 24 febbraio 2025, è descritto come "maintenance release" - le novità principali sono starter kit aggiornati e l'aggiornamento delle dipendenze (Carbon 3, PHPUnit 11). La struttura slim è una scelta architetturale, non un requisito di upgrade.

Detto questo, la migrazione ha senso quando la frammentazione della configurazione è diventata un problema reale: nuovi sviluppatori che impiegano ore per capire dove sono registrati middleware e route, logica di bootstrap sparsa in più Provider che nessuno ricorda di manutenere, e test che richiedono mock elaborati dei Kernel per simulare configurazioni diverse. La struttura slim risolve questi problemi centralizzando routing, middleware ed eccezioni in un unico file con un'API fluente.

Il nuovo bootstrap/app.php: tutto in un unico punto

Il cuore della struttura slim è bootstrap/app.php, che usa Application::configure() con tre callback - withRouting, withMiddleware, withExceptions - per sostituire Http/Kernel.php, Console/Kernel.php, RouteServiceProvider e Exceptions/Handler.php:

use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        api: __DIR__.'/../routes/api.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
        then: function () {
            RateLimiter::for('api', function (Request $request) {
                return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
            });
        },
    )
    ->withMiddleware(function (Middleware $middleware) {
        $middleware->alias([
            'is_admin' => \App\Http\Middleware\EnsureUserIsAdmin::class,
            'locale' => \App\Http\Middleware\SetLocale::class,
        ]);
    })
    ->withExceptions(function (Exceptions $exceptions) {
        $exceptions->render(function (\Symfony\Component\HttpKernel\Exception\NotFoundHttpException $e, Request $request) {
            if ($request->is('api/*')) {
                return response()->json(['message' => 'Risorsa non trovata.'], 404);
            }
        });
    })
    ->create();

Quello che prima richiedeva Http/Kernel.php (middleware globali, gruppi, alias), RouteServiceProvider (caricamento rotte, rate limiter) e Exceptions/Handler.php (rendering custom) è ora in un unico file con un'API dichiarativa. Laravel 11+ gestisce internamente i middleware del gruppo web (EncryptCookies, StartSession, VerifyCsrfToken) - nel nuovo withMiddleware vanno registrati solo i middleware custom dell'applicativo.

La migrazione pratica: eliminare i file obsoleti

La migrazione segue un ordine preciso per evitare rotture. Primo: creare il nuovo bootstrap/app.php con la configurazione migrata da Kernel e Provider, senza eliminare ancora i vecchi file. Secondo: verificare che l'applicativo funzioni con entrambe le configurazioni presenti (Laravel privilegia bootstrap/app.php se usa la nuova struttura). Terzo: eliminare i file obsoleti uno alla volta - Http/Kernel.php, Console/Kernel.php, RouteServiceProvider, AuthServiceProvider (se le policy seguono le convenzioni di naming, l'autodiscovery le registra automaticamente), EventServiceProvider (l'event discovery è attivo di default).

Per applicativi di medie dimensioni, Laravel Shift automatizza la maggior parte della migrazione strutturale generando un PR con le modifiche necessarie - inclusa la conversione dei Kernel, la migrazione dei Provider e l'aggiornamento delle dipendenze. Il costo ($39 per lo shift L10→L11) è spesso inferiore al tempo che richiederebbe una migrazione manuale su un codebase con logica custom nei Kernel.

Due attenzioni: il file routes/api.php non è più incluso di default in Laravel 11+ - se l'applicativo lo usa, va specificato esplicitamente in withRouting o installato con php artisan install:api. E il file routes/console.php cambia ruolo: da file caricato dal Console/Kernel a file che usa la facade Schedule direttamente per definire i task schedulati.

Errori comuni nella migrazione strutturale

Il primo errore è migrare la struttura durante l'upgrade di versione. Sono due operazioni distinte: prima aggiorna a Laravel 12 mantenendo la struttura di Laravel 10 (la guida ufficiale stima 5 minuti), verifica che tutto funzioni, poi migra alla struttura slim come operazione separata. Mescolare le due operazioni rende impossibile isolare la causa di eventuali regressioni.

Il secondo è dimenticare middleware registrati in Http/Kernel.php che non hanno equivalente nella configurazione interna di Laravel 11+. I middleware standard del gruppo web (cookies, sessioni, CSRF) sono gestiti internamente, ma qualsiasi middleware custom - rate limiter specifici, middleware di tenant isolation, middleware di locale - deve essere esplicitamente migrato in withMiddleware. Un grep -r 'middleware' app/Http/Kernel.php prima della rimozione è il check minimo.

Il terzo è eliminare i Service Provider senza verificare che l'autodiscovery copra le registrazioni. Le policy vengono scoperte automaticamente solo se seguono la convenzione App\Policies\ModelPolicy - policy con nomi non convenzionali devono essere registrate esplicitamente in AppServiceProvider tramite Gate::policy(). Lo stesso vale per gli event listener: l'event discovery funziona solo con listener type-hinted nell'argomento del metodo handle.

I test automatici sono la rete di sicurezza indispensabile per questa migrazione - senza di essi, l'unico modo di verificare che nessun middleware o provider sia stato perso è testare manualmente ogni rotta dell'applicativo. L'aggiornamento da versioni legacy di Laravel e Symfony copre il percorso completo per applicativi che partono da versioni più datate (Laravel 5-9), dove la distanza strutturale è significativamente maggiore. Per conoscere il mio approccio alla modernizzazione di applicativi Laravel, visita la mia pagina professionale. Se il tuo applicativo Laravel 10 necessita di un aggiornamento strutturale e vuoi pianificare la migrazione senza rischi, contattami per una consulenza dedicata - partiamo dall'analisi della configurazione attuale e dalla copertura dei test.

Ultima modifica: