Vai al contenuto principale

Cos’è un controller

Anziché definire tutta la logica delle richieste come closure nei file di route, puoi organizzarla usando classi “controller”. I controller raccolgono in un’unica classe la logica di gestione delle richieste correlate. Ad esempio, la classe UserController può gestire tutte le richieste in ingresso relative agli utenti: visualizzazione, creazione, aggiornamento, eliminazione. Di default i controller si trovano nella directory app/Http/Controllers.

Creazione di un controller

Per generare rapidamente un nuovo controller usa il comando Artisan make:controller. Tutti i controller dell’applicazione sono di default nella directory app/Http/Controllers.
php artisan make:controller UserController

Controller di base

Una classe controller può avere alcuni metodi public che rispondono alle richieste HTTP.
<?php

namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\View\View;

class UserController extends Controller
{
    /**
     * Mostra il profilo dell'utente indicato
     */
    public function show(string $id): View
    {
        return view('user.profile', [
            'user' => User::findOrFail($id)
        ]);
    }
}
Una volta creati la classe e il metodo, puoi definire la route al metodo del controller come segue.
use App\Http\Controllers\UserController;

Route::get('/user/{id}', [UserController::class, 'show']);
Quando una richiesta corrisponde all’URI della route, viene chiamato il metodo show di App\Http\Controllers\UserController e i parametri di route vengono passati al metodo.
I controller non devono necessariamente estendere una classe base. È però comodo estendere un controller base per condividere metodi tra tutti i controller.

Controller a singola action

Se un’azione del controller è particolarmente complessa, può essere comodo dedicare l’intera classe a quella singola azione. Per farlo definisci un unico metodo __invoke.
<?php

namespace App\Http\Controllers;

class ProvisionServer extends Controller
{
    /**
     * Provisiona un nuovo web server
     */
    public function __invoke()
    {
        // ...
    }
}
Nella registrazione della route non devi specificare il metodo del controller: passa solo il nome della classe.
use App\Http\Controllers\ProvisionServer;

Route::post('/server', ProvisionServer::class);
Puoi generare un controller invokable con l’opzione --invokable del comando make:controller.
php artisan make:controller ProvisionServer --invokable

Resource controller

Se pensi a ciascun modello Eloquent come a una “risorsa”, di norma applichi lo stesso insieme di operazioni (CRUD) a ciascuna risorsa. Il resource routing di Laravel assegna con una sola riga di codice a un controller le route CRUD tipiche. Con l’opzione --resource di make:controller generi rapidamente un controller che gestisce queste azioni.
php artisan make:controller PhotoController --resource
Il comando crea app/Http/Controllers/PhotoController.php con gli scaffold di tutte le operazioni di risorsa. Poi registra la route di risorsa che punta al controller.
use App\Http\Controllers\PhotoController;

Route::resource('photos', PhotoController::class);
Questa singola riga di dichiarazione crea più route che gestiscono le varie azioni sulla risorsa. Il controller generato include già i metodi corrispondenti a ciascuna azione.
Metodo HTTPURIAzioneNome route
GET/photosindexphotos.index
GET/photos/createcreatephotos.create
POST/photosstorephotos.store
GET/photos/{photo}showphotos.show
GET/photos/{photo}/editeditphotos.edit
PUT/PATCH/photos/{photo}updatephotos.update
DELETE/photos/{photo}destroyphotos.destroy
Con il comando php artisan route:list puoi ottenere una panoramica veloce delle route dell’applicazione.

Route di risorsa parziali

Quando dichiari le route di risorsa puoi indicare un sottoinsieme di azioni.
use App\Http\Controllers\PhotoController;

Route::resource('photos', PhotoController::class)->only([
    'index', 'show'
]);

Route::resource('photos', PhotoController::class)->except([
    'create', 'store', 'update', 'destroy'
]);

Route di risorsa API

Quando dichiari route di risorsa da usare in un’API, spesso vuoi escludere le route che restituiscono template HTML come create ed edit. Con il metodo apiResource queste due route vengono escluse automaticamente.
use App\Http\Controllers\PhotoController;

Route::apiResource('photos', PhotoController::class);

Dependency injection

Constructor injection

Il service container di Laravel viene usato per risolvere le dipendenze di tutti i controller Laravel. Perciò puoi indicare con il type hint nel costruttore del controller le dipendenze necessarie. Le dipendenze dichiarate vengono risolte automaticamente e iniettate nell’istanza del controller.
<?php

namespace App\Http\Controllers;

use App\Repositories\UserRepository;

class UserController extends Controller
{
    /**
     * Crea una nuova istanza del controller
     */
    public function __construct(
        protected UserRepository $users,
    ) {}
}

Method injection

Oltre al constructor injection, puoi indicare con il type hint le dipendenze di un metodo. Un caso d’uso comune è iniettare un’istanza Illuminate\Http\Request in un metodo del controller.
<?php

namespace App\Http\Controllers;

use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;

class UserController extends Controller
{
    /**
     * Salva un nuovo utente
     */
    public function store(Request $request): RedirectResponse
    {
        $name = $request->name;

        // Logica di salvataggio dell'utente...

        return redirect('/users');
    }
}
Se il metodo del controller riceve anche input dai parametri di route, elenca gli argomenti di route dopo le altre dipendenze. Ad esempio, se la route è definita così:
use App\Http\Controllers\UserController;

Route::put('/user/{id}', [UserController::class, 'update']);
Puoi definire il metodo del controller in modo da usare il type hint di Illuminate\Http\Request e accedere al parametro id.
<?php

namespace App\Http\Controllers;

use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;

class UserController extends Controller
{
    /**
     * Aggiorna l'utente indicato
     */
    public function update(Request $request, string $id): RedirectResponse
    {
        // Logica di aggiornamento dell'utente...

        return redirect('/users');
    }
}
Sfruttando la dependency injection puoi iniettare più facilmente dei mock nei test, migliorando la testabilità del codice.

Prossimi passi

Routing

Rivedi come definire le route e integrarle con i controller.
Ultima modifica il 13 luglio 2026