Prologo
Primi Passi
Architettura
Le Basi
- Routing
- Middleware
- Protezione da CSRF
- Controller
- Richieste
- Risposte
- Views
- Blade
- Vite
- URL
- Sessioni
- Validazione
- Errori
- Logging
Approfondimenti
- Artisan
- Broadcasting
- Cache
- Collezioni
- Concorrenza
- Contesto
- Contratti
- Eventi
- File System
- Helpers
- Client HTTP
- Localizzazione
- Notifiche
- Sviluppo di Package
- Processi
- Code
- Rate-limiting
- Stringhe
- Scheduling di Task
Sicurezza
Database
Eloquent ORM
Testing
Package
Routing
- Routing di base
- Parametri delle Rotte
- Rotte Nominate
- Gruppi di Rotte
- Route Model Binding
- Rotta di fallback
- Rate Limiting
- Workaround per i Metodi dei Form
- Accesso alla Rotta Attuale
- Cross-Origin Resource Sharing (CORS)
- Cache delle Route
Routing di base
Le rotte più semplici di Laravel accettano un URI e una closure, offrendo un metodo molto semplice ed espressivo per definire rotte e comportamenti senza file di configurazione del routing complicati:
use Illuminate\Support\Facades\Route;
Route::get('/greeting', function () {
return 'Hello World';
});
I File delle Rotte
Tutte le rotte di Laravel sono definite nei tuoi file di rotte, che si trovano nella directory routes
. Questi file vengono caricati automaticamente da Laravel utilizzando la configurazione specificata nel file bootstrap/app.php
della tua applicazione. Il file routes/web.php
definisce le rotte per la tua interfaccia web. Queste rotte sono assegnate al web
middleware group, che fornisce funzionalità come lo stato della sessione e la protezione CSRF.
Per la maggior parte delle applicazioni, inizierai definendo le rotte nel file routes/web.php
. Le rotte definite in routes/web.php
possono essere accessibili inserendo l’URL della rotta definita nel tuo browser. Ad esempio, puoi accedere alla seguente rotta navigando su http://example.com/user
nel tuo browser:
use App\Http\Controllers\UserController;
Route::get('/user', [UserController::class, 'index']);
Rotte API
Se la tua applicazione offrirà anche una API stateless, puoi abilitare il routing API usando il comando Artisan install:api
:
php artisan install:api
Il comando install:api
installa Laravel Sanctum, che fornisce una guardia di autenticazione token API robusta ma semplice, utilizzabile per autenticare client API di terze parti, SPA o applicazioni mobili. Inoltre, il comando install:api
crea il file routes/api.php
:
Route::get('/user', function (Request $request) {
return $request->user();
})->middleware('auth:sanctum');
Le rotte in routes/api.php
sono senza stato e assegnate al gruppo di middleware api
. Inoltre, il prefisso URI /api
viene applicato automaticamente a queste rotte, quindi non è necessario applicarlo manualmente a ogni rotta nel file. Puoi cambiare il prefisso modificando il file bootstrap/app.php
della tua applicazione:
->withRouting(
api: __DIR__.'/../routes/api.php',
apiPrefix: 'api/admin',
// ...
)
Metodi Disponibili del Router
Il router permette di registrare percorsi che rispondono a qualsiasi verbo HTTP:
Route::get($uri, $callback);
Route::post($uri, $callback);
Route::put($uri, $callback);
Route::patch($uri, $callback);
Route::delete($uri, $callback);
Route::options($uri, $callback);
A volte potresti aver bisogno di registrare un percorso che risponde a più verb HTTP. Puoi farlo usando il metodo match
. Oppure, puoi registrare un percorso che risponde a tutti i verb HTTP usando il metodo any
:
Route::match(['get', 'post'], '/', function () {
// ...
});
Route::any('/', function () {
// ...
});
Quando definisci più percorsi che condividono lo stesso URI, i percorsi che usano i metodi
get
,post
,put
,patch
,delete
eoptions
dovrebbero essere definiti prima di quelli che usano i metodiany
,match
eredirect
. Questo garantisce che la richiesta in arrivo venga abbinata al percorso corretto.
Iniezione delle Dipendenze
Puoi specificare le dipendenze necessarie per la tua route nella callback della route. Le dipendenze dichiarate verranno automaticamente risolte e iniettate nella callback dal service container di Laravel. Ad esempio, puoi specificare la classe Illuminate\Http\Request
per avere la richiesta HTTP corrente automaticamente iniettata nella tua callback:
use Illuminate\Http\Request;
Route::get('/users', function (Request $request) {
// ...
});
Protezione CSRF
Ricorda che qualsiasi modulo HTML che punti a rotte POST
, PUT
, PATCH
o DELETE
definite nel file delle rotte web
deve includere un campo token CSRF. Altrimenti, la richiesta sarà respinta. Puoi leggere di più sulla protezione CSRF nella documentazione CSRF:
<form method="POST" action="/profile">
@csrf
...
</form>
Redirect
Se stai definendo una rotta che reindirizza a un’altra URI, puoi usare il metodo Route::redirect
. Questo metodo offre una scorciatoia comoda, così non devi definire una rotta completa o un controller per eseguire un semplice reindirizzamento:
Route::redirect('/here', '/there');
Di default, Route::redirect
restituisce un codice di stato 302
. Puoi personalizzare il codice di stato usando il terzo parametro opzionale:
Route::redirect('/here', '/there', 301);
Oppure, puoi usare il metodo Route::permanentRedirect
per restituire un codice di stato 301
:
Route::permanentRedirect('/here', '/there');
Quando usi parametri di rotta nelle rotte di reindirizzamento, i seguenti parametri sono riservati da Laravel e non possono essere utilizzati:
destination
estatus
.
Route e View
Se il tuo percorso deve solo restituire una view, puoi usare il metodo Route::view
. Come il metodo redirect
, questo metodo offre una scorciatoia semplice così non devi definire un percorso completo o un controller. Il metodo view
accetta un URI come primo argomento e il nome della view come secondo argomento. Inoltre, puoi fornire un array di dati da passare alla view come terzo argomento opzionale:
Route::view('/welcome', 'welcome');
Route::view('/welcome', 'welcome', ['name' => 'Taylor']);
Quando usi parametri di percorso nelle route di vista, i seguenti parametri sono riservati da Laravel e non possono essere utilizzati:
view
,data
,status
eheaders
.
Elenco delle Rotte
Il comando Artisan route:list
può fornire facilmente una panoramica di tutte le rotte definite dalla tua applicazione:
php artisan route:list
Per impostazione predefinita, i middleware delle rotte assegnati a ciascuna rotta non verranno mostrati nell’output di route:list
; tuttavia, puoi chiedere a Laravel di visualizzare i middleware delle rotte e i nomi dei gruppi di middleware aggiungendo l’opzione -v
al comando:
php artisan route:list -v
# Espandi i gruppi di middleware...
php artisan route:list -vv
Puoi anche istruire Laravel a mostrare solo le rotte che iniziano con un determinato URI:
php artisan route:list --path=api
Inoltre, puoi istruire Laravel a nascondere tutte le rotte definite dai pacchetti di terze parti fornendo l’opzione --except-vendor
quando esegui il comando route:list
:
php artisan route:list --except-vendor
Allo stesso modo, puoi anche istruire Laravel a mostrare solo le rotte definite dai pacchetti di terze parti fornendo l’opzione --only-vendor
quando esegui il comando route:list
:
php artisan route:list --only-vendor
Personalizzazione del Routing
Per impostazione predefinita, le rotte della tua applicazione sono configurate e caricate dal file bootstrap/app.php
:
<?php
use Illuminate\Foundation\Application;
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__.'/../routes/web.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
)->create();
Tuttavia, a volte potresti voler definire un file completamente nuovo per contenere un sottoinsieme delle rotte della tua applicazione. Per fare ciò, puoi fornire una closure then
al metodo withRouting
. All’interno di questa closure, puoi registrare eventuali rotte aggiuntive necessarie per la tua applicazione:
use Illuminate\Support\Facades\Route;
->withRouting(
web: __DIR__.'/../routes/web.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
then: function () {
Route::middleware('api')
->prefix('webhooks')
->name('webhooks.')
->group(base_path('routes/webhooks.php'));
},
)
Oppure, puoi anche prendere il completo controllo sulla registrazione delle rotte fornendo una closure using
al metodo withRouting
. Quando questo argomento è passato, il framework non registrerà alcuna rotta HTTP e sarai tu a dover registrare manualmente tutte le rotte:
use Illuminate\Support\Facades\Route;
->withRouting(
commands: __DIR__.'/../routes/console.php',
using: function () {
Route::middleware('api')
->prefix('api')
->group(base_path('routes/api.php'));
Route::middleware('web')
->group(base_path('routes/web.php'));
},
)
Parametri delle Rotte
Parametri Richiesti
A volte avrai bisogno di catturare parti dell’URI nella tua rotta. Ad esempio, potresti dover ottenere l’ID di un utente dall’URL. Puoi farlo definendo parametri di rotta:
Route::get('/user/{id}', function (string $id) {
return 'User '.$id;
});
Puoi definire quanti parametri di rotta ti servono:
Route::get('/posts/{post}/comments/{comment}', function (string $postId, string $commentId) {
// ...
});
I parametri di rotta sono sempre racchiusi tra parentesi {}
e devono contenere solo caratteri alfabetici. Gli underscore (_
) sono accettabili nei nomi dei parametri di rotta. I parametri di rotta vengono iniettati nei callback delle rotte o nei controller in base al loro ordine, quindi i nomi degli argomenti del callback o del controller non hanno importanza.
Parametri e Iniezione delle Dipendenze
Se la tua rotta ha delle dipendenze che desideri vengano automaticamente iniettate nel callback della rotta dal service container di Laravel, dovresti elencare i parametri della rotta dopo le dipendenze:
use Illuminate\Http\Request;
Route::get('/user/{id}', function (Request $request, string $id) {
return 'User '.$id;
});
Parametri Opzionali
A volte potrebbe essere necessario specificare un parametro di rotta che non è sempre presente nell’URI. Puoi farlo aggiungendo un ?
dopo il nome del parametro. Ricorda di assegnare un valore predefinito alla variabile corrispondente della rotta:
Route::get('/user/{name?}', function (?string $name = null) {
return $name;
});
Route::get('/user/{name?}', function (?string $name = 'John') {
return $name;
});
Vincoli con Regex
Puoi limitare il formato dei parametri della tua route utilizzando il metodo where
su un’istanza di route. Il metodo where
accetta il nome del parametro e un’espressione regolare che definisce come il parametro deve essere vincolato:
Route::get('/user/{name}', function (string $name) {
// ...
})->where('name', '[A-Za-z]+');
Route::get('/user/{id}', function (string $id) {
// ...
})->where('id', '[0-9]+');
Route::get('/user/{id}/{name}', function (string $id, string $name) {
// ...
})->where(['id' => '[0-9]+', 'name' => '[a-z]+']);
Per comodità, alcuni pattern di espressioni regolari comunemente usati hanno metodi helper che ti permettono di aggiungere rapidamente vincoli di pattern alle tue routes:
Route::get('/user/{id}/{name}', function (string $id, string $name) {
// ...
})->whereNumber('id')->whereAlpha('name');
Route::get('/user/{name}', function (string $name) {
// ...
})->whereAlphaNumeric('name');
Route::get('/user/{id}', function (string $id) {
// ...
})->whereUuid('id');
Route::get('/user/{id}', function (string $id) {
// ...
})->whereUlid('id');
Route::get('/category/{category}', function (string $category) {
// ...
})->whereIn('category', ['movie', 'song', 'painting']);
Route::get('/category/{category}', function (string $category) {
// ...
})->whereIn('category', CategoryEnum::cases());
Se la richiesta in arrivo non corrisponde ai vincoli del pattern della route, verrà restituita una risposta HTTP 404.
Vincoli Globali
Se desideri che un parametro di route sia sempre limitato da una determinata espressione regolare, puoi usare il metodo pattern
. Dovresti definire questi pattern nel metodo boot
della classe App\Providers\AppServiceProvider
della tua applicazione:
use Illuminate\Support\Facades\Route;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Route::pattern('id', '[0-9]+');
}
Una volta definito il pattern, viene applicato automaticamente a tutte le route che usano quel nome di parametro:
Route::get('/user/{id}', function (string $id) {
// Eseguito solo se {id} è numerico...
});
Slash Codificati
Il componente di routing di Laravel consente tutti i caratteri tranne /
nei valori dei parametri delle route. Devi esplicitamente permettere /
nel tuo segnaposto usando una espressione regolare nella condizione where
:
Route::get('/search/{search}', function (string $search) {
return $search;
})->where('search', '.*');
Gli slash codificati sono supportati solo nell’ultimo segmento della route.
Rotte Nominate
Le rotte nominate consentono di generare URL o reindirizzamenti in modo semplice per rotte specifiche. Puoi assegnare un nome a una rotta concatenando il metodo name
alla definizione della rotta:
Route::get('/user/profile', function () {
// ...
})->name('profile');
Puoi anche specificare nomi per le rotte delle azioni del controller:
Route::get(
'/user/profile',
[UserProfileController::class, 'show']
)->name('profile');
I nomi delle rotte devono essere sempre unici.
Generare URL per Rotte Nominate
Una volta assegnato un nome a una determinata rotta, puoi usare il nome della rotta per generare URL o reindirizzamenti tramite le funzioni helper route
e redirect
di Laravel:
// Generare URL...
$url = route('profile');
// Generare Reindirizzamenti...
return redirect()->route('profile');
return to_route('profile');
Se la rotta nominata definisce dei parametri, puoi passarli come secondo argomento alla funzione route
. I parametri forniti verranno automaticamente inseriti nell’URL generato nelle posizioni corrette:
Route::get('/user/{id}/profile', function (string $id) {
// ...
})->name('profile');
$url = route('profile', ['id' => 1]);
Se passi parametri aggiuntivi nell’array, queste coppie chiave/valore saranno aggiunte automaticamente alla stringa di query dell’URL generato:
Route::get('/user/{id}/profile', function (string $id) {
// ...
})->name('profile');
$url = route('profile', ['id' => 1, 'photos' => 'yes']);
// /user/1/profile?photos=yes
A volte potresti voler specificare valori predefiniti validi per tutta la richiesta per i parametri dell’URL, come la lingua corrente. Per fare ciò, puoi usare il
URL::defaults
method.
Verificare la Rotta Corrente
Se vuoi determinare se la richiesta corrente è stata indirizzata a una route con un determinato nome, puoi usare il metodo named
su un’istanza di Route. Ad esempio, puoi controllare il nome della route corrente da un middleware di route:
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
/**
* Gestisci una richiesta in arrivo.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response
{
if ($request->route()->named('profile')) {
// ...
}
return $next($request);
}
Gruppi di Rotte
I gruppi di rotte permettono di condividere attributi delle rotte, come middleware, su un gran numero di rotte senza dover definire tali attributi su ogni singola rotta.
I gruppi annidati hanno l’obiettivo di "fondere" intelligentemente gli attributi con il gruppo padre. Middleware e condizioni where
vengono uniti mentre nomi e prefissi vengono aggiunti. I delimitatori di namespace e le barre nei prefissi URI vengono aggiunti automaticamente dove opportuno.
Middleware
Per assegnare middleware a tutte le rotte di un gruppo, puoi usare il metodo middleware
prima di definire il gruppo. I middleware vengono eseguiti nell’ordine in cui sono elencati nell’array:
Route::middleware(['first', 'second'])->group(function () {
Route::get('/', function () {
// Usa il middleware first & second...
});
Route::get('/user/profile', function () {
// Usa il middleware first & second...
});
});
Controller
Se un gruppo di route utilizza lo stesso controller, puoi usare il metodo controller
per definire il controller comune per tutte le route all’interno del gruppo. Poi, quando definisci le route, devi solo specificare il metodo del controller che invocano:
use App\Http\Controllers\OrderController;
Route::controller(OrderController::class)->group(function () {
Route::get('/orders/{id}', 'show');
Route::post('/orders', 'store');
});
Routing dei Sottodomini
I gruppi di route possono essere utilizzati anche per gestire il routing dei sottodomini. I sottodomini possono avere parametri di route proprio come gli URI delle route, permettendoti di catturare una parte del sottodominio da utilizzare nella tua route o nel tuo controller. Il sottodominio può essere specificato chiamando il metodo domain
prima di definire il gruppo:
Route::domain('{account}.example.com')->group(function () {
Route::get('/user/{id}', function (string $account, string $id) {
// ...
});
});
Per garantire che le tue route dei sottodomini siano raggiungibili, dovresti registrare le route dei sottodomini prima di registrare le route del dominio principale. Questo impedirà alle route del dominio principale di sovrascrivere le route dei sottodomini che hanno lo stesso percorso URI.
Prefissi delle Route
Il metodo prefix
può essere usato per aggiungere un prefisso a ogni route nel gruppo con un determinato URI. Ad esempio, potresti voler aggiungere admin
come prefisso a tutti gli URI delle route nel gruppo:
Route::prefix('admin')->group(function () {
Route::get('/users', function () {
// Corrisponde all'URL "/admin/users"
});
});
Prefissi dei Nomi delle Rotte
Il metodo name
può essere utilizzato per aggiungere un prefisso a ogni nome di rotta nel gruppo con una stringa specificata. Per esempio, potresti voler aggiungere il prefisso admin
ai nomi di tutte le rotte nel gruppo. La stringa fornita viene aggiunta al nome della rotta esattamente come specificato, quindi assicuriamoci di includere il carattere .
finale nel prefisso:
Route::name('admin.')->group(function () {
Route::get('/users', function () {
// Route assigned name "admin.users"...
})->name('users');
});
Route Model Binding
Quando passi un ID di un modello a una route o a un’azione del controller, spesso devi interrogare il database per ottenere il modello corrispondente a quell’ID. Il route model binding di Laravel offre un modo semplice per iniettare automaticamente le istanze del modello direttamente nelle tue route. Ad esempio, invece di passare l’ID di un utente, puoi passare l’intera istanza del modello User
che corrisponde a quell’ID.
Binding implicito
Laravel risolve automaticamente i modelli Eloquent definiti nelle route o nelle azioni del controller i cui nomi delle variabili con hint di tipo corrispondono al nome di un segmento della route. Ad esempio:
use App\Models\User;
Route::get('/users/{user}', function (User $user) {
return $user->email;
});
Poiché la variabile $user
ha un hint di tipo come il modello Eloquent App\Models\User
e il nome della variabile corrisponde al segmento URI {user}
, Laravel inietterà automaticamente l’istanza del modello che ha un ID corrispondente al valore del parametro nella URI della richiesta. Se non viene trovata un’istanza del modello corrispondente nel database, verrà generata automaticamente una risposta HTTP 404.
Naturalmente, il binding implicito è possibile anche quando si utilizzano i metodi del controller. Anche in questo caso, nota che il segmento URI {user}
corrisponde alla variabile $user
nel controller che contiene un hint di tipo App\Models\User
:
use App\Http\Controllers\UserController;
use App\Models\User;
// Definizione della route...
Route::get('/users/{user}', [UserController::class, 'show']);
// Definizione del metodo del controller...
public function show(User $user)
{
return view('user.profile', ['user' => $user]);
}
Recupero dei record soft-deleted
Normalmente, il binding implicito dei modelli non recupera quelli che sono stati eliminati con soft-delete. Tuttavia, puoi fare in modo che il binding implicito recuperi questi modelli aggiungendo il metodo withTrashed
alla definizione della tua route:
use App\Models\User;
Route::get('/users/{user}', function (User $user) {
return $user->email;
})->withTrashed();
Personalizzazione della Chiave
A volte potresti voler risolvere i modelli Eloquent utilizzando una colonna diversa da id
. Per farlo, puoi specificare la colonna nella definizione del parametro della rotta:
use App\Models\Post;
Route::get('/posts/{post:slug}', function (Post $post) {
return $post;
});
Se desideri che il binding del modello utilizzi sempre una colonna del database diversa da id
quando recupera una determinata classe di modello, puoi sovrascrivere il metodo getRouteKeyName
nel modello Eloquent:
/**
* Ottieni la chiave della rotta per il modello.
*/
public function getRouteKeyName(): string
{
return 'slug';
}
Chiavi Personalizzate e Scoping
Quando si effettuano binding impliciti di più modelli Eloquent in una singola definizione di route, potresti voler limitare il secondo modello Eloquent in modo che sia figlio del modello precedente. Ad esempio, considera questa definizione di route che recupera un post del blog per slug di un utente specifico:
use App\Models\Post;
use App\Models\User;
Route::get('/users/{user}/posts/{post:slug}', function (User $user, Post $post) {
return $post;
});
Quando si utilizza un binding implicito con chiave personalizzata come parametro di route annidato, Laravel limiterà automaticamente la query per recuperare il modello annidato dal suo genitore utilizzando le convenzioni per indovinare il nome della relazione sul genitore. In questo caso, si presumerà che il modello User
abbia una relazione chiamata posts
(la forma plurale del nome del parametro di route) che può essere usata per recuperare il modello Post
.
Se desideri, puoi istruire Laravel a limitare i binding "child" anche quando non viene fornita una chiave personalizzata. Per farlo, puoi invocare il metodo scopeBindings
durante la definizione della route:
use App\Models\Post;
use App\Models\User;
Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) {
return $post;
})->scopeBindings();
Oppure, puoi istruire un intero gruppo di definizioni di route a usare ambiti di binding:
Route::scopeBindings()->group(function () {
Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) {
return $post;
});
});
In modo simile, puoi istruire esplicitamente Laravel a non limitare i binding invocando il metodo withoutScopedBindings
:
Route::get('/users/{user}/posts/{post:slug}', function (User $user, Post $post) {
return $post;
})->withoutScopedBindings();
Personalizzare il comportamento per i modelli mancanti
Normalmente, viene generata una risposta HTTP 404 se un modello vincolato implicitamente non viene trovato. Tuttavia, puoi personalizzare questo comportamento chiamando il metodo missing
quando definisci la tua rotta. Il metodo missing
accetta una closure che verrà eseguita se un modello vincolato implicitamente non viene trovato:
use App\Http\Controllers\LocationsController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Redirect;
Route::get('/locations/{location:slug}', [LocationsController::class, 'show'])
->name('locations.view')
->missing(function (Request $request) {
return Redirect::route('locations.index');
});
Binding implicito degli Enum
PHP 8.1 ha introdotto il supporto per gli Enum. Per completare questa funzionalità, Laravel ti permette di specificare un backed Enum nella definizione della tua route e Laravel chiamerà la route solo se quel segmento della route corrisponde a un valore Enum valido. Altrimenti, verrà automaticamente restituita una risposta HTTP 404. Ad esempio, dato il seguente Enum:
<?php
namespace App\Enums;
enum Category: string
{
case Fruits = 'fruits';
case People = 'people';
}
Puoi definire una route che verrà chiamata solo se il segmento {category}
della route è fruits
o people
. Altrimenti, Laravel restituirà una risposta HTTP 404:
use App\Enums\Category;
use Illuminate\Support\Facades\Route;
Route::get('/categories/{category}', function (Category $category) {
return $category->value;
});
Binding Esplicito
Non è necessario utilizzare la risoluzione implicita dei modelli basata su convenzioni di Laravel per utilizzare il model binding. Puoi anche definire esplicitamente come i parametri delle route corrispondono ai modelli. Per registrare un binding esplicito, usa il metodo model
del router per specificare la classe per un determinato parametro. Dovresti definire i tuoi binding espliciti all’inizio del metodo boot
della tua classe AppServiceProvider
:
use App\Models\User;
use Illuminate\Support\Facades\Route;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Route::model('user', User::class);
}
Successivamente, definisci una route che contiene un parametro {user}
:
use App\Models\User;
Route::get('/users/{user}', function (User $user) {
// ...
});
Poiché abbiamo legato tutti i parametri {user}
al modello App\Models\User
, un’istanza di quella classe sarà iniettata nella route. Ad esempio, una richiesta a users/1
inietterà l’istanza User
dal database che ha un ID di 1
.
Se non viene trovata un’istanza del modello corrispondente nel database, verrà generata automaticamente una risposta HTTP 404.
Personalizzare la Logica di Risoluzione
Se desideri definire la tua logica di risoluzione del binding del modello, puoi utilizzare il metodo Route::bind
. La closure che passi al metodo bind
riceverà il valore del segmento URI e dovrebbe restituire l’istanza della classe che verrà iniettata nella route. Anche in questo caso, questa personalizzazione dovrebbe avvenire nel metodo boot
del AppServiceProvider
della tua applicazione:
use App\Models\User;
use Illuminate\Support\Facades\Route;
/**
* Bootstrap di qualsiasi servizio dell'applicazione.
*/
public function boot(): void
{
Route::bind('user', function (string $value) {
return User::where('name', $value)->firstOrFail();
});
}
In alternativa, puoi sovrascrivere il metodo resolveRouteBinding
nel tuo modello Eloquent. Questo metodo riceverà il valore del segmento URI e dovrebbe restituire l’istanza della classe che verrà iniettata nella route:
/**
* Recupera il modello per un valore associato.
*
* @param mixed $value
* @param string|null $field
* @return \Illuminate\Database\Eloquent\Model|null
*/
public function resolveRouteBinding($value, $field = null)
{
return $this->where('name', $value)->firstOrFail();
}
Se una route utilizza lo scoping del binding implicito, verrà utilizzato il metodo resolveChildRouteBinding
per risolvere il binding figlio del modello genitore:
/**
* Recupera il modello figlio per un valore associato.
*
* @param string $childType
* @param mixed $value
* @param string|null $field
* @return \Illuminate\Database\Eloquent\Model|null
*/
public function resolveChildRouteBinding($childType, $value, $field)
{
return parent::resolveChildRouteBinding($childType, $value, $field);
}
Rotta di fallback
Usando il metodo Route::fallback
, puoi definire una route che verrà eseguita quando nessun’altra route corrisponde alla richiesta in arrivo. Di solito, le richieste non gestite mostreranno automaticamente una pagina "404" tramite il gestore delle eccezioni dell’applicazione. Tuttavia, poiché solitamente definisci la route fallback
nel file routes/web.php
, tutto il middleware nel gruppo middleware web
si applicherà alla route. Puoi aggiungere ulteriori middleware a questa route se necessario:
Route::fallback(function () {
// ...
});
Rate Limiting
Definizione dei Rate Limiter
Laravel include servizi di limitazione del traffico potenti e personalizzabili che puoi utilizzare per restringere la quantità di traffico per una determinata rotta o gruppo di rotte. Per iniziare, dovresti definire configurazioni di rate limiter che soddisfino le esigenze della tua applicazione.
I rate limiter possono essere definiti all’interno del metodo boot
della classe App\Providers\AppServiceProvider
della tua applicazione:
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
/**
* Bootstrap any application services.
*/
protected function boot(): void
{
RateLimiter::for('api', function (Request $request) {
return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
});
}
I rate limiter sono definiti utilizzando il metodo for
della facade RateLimiter
. Il metodo for
accetta un nome per il rate limiter e una closure che restituisce la configurazione del limite che dovrebbe applicarsi alle rotte assegnate al rate limiter. Le configurazioni dei limiti sono istanze della classe Illuminate\Cache\RateLimiting\Limit
. Questa classe contiene metodi "builder" utili per definire rapidamente il tuo limite. Il nome del rate limiter può essere qualsiasi stringa tu desideri:
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
/**
* Bootstrap any application services.
*/
protected function boot(): void
{
RateLimiter::for('global', function (Request $request) {
return Limit::perMinute(1000);
});
}
Se la richiesta in arrivo supera il limite di velocità specificato, Laravel restituirà automaticamente una risposta con codice di stato HTTP 429. Se desideri definire una tua risposta personalizzata che dovrebbe essere restituita in caso di superamento del limite, puoi utilizzare il metodo response
:
RateLimiter::for('global', function (Request $request) {
return Limit::perMinute(1000)->response(function (Request $request, array $headers) {
return response('Custom response...', 429, $headers);
});
});
Poiché i callback dei rate limiter ricevono l’istanza della richiesta HTTP in arrivo, puoi costruire dinamicamente il limite appropriato in base alla richiesta entrante o all’utente autenticato:
RateLimiter::for('uploads', function (Request $request) {
return $request->user()->vipCustomer()
? Limit::none()
: Limit::perMinute(100);
});
Segmentazione del Rate-limiter
A volte potresti voler segmentare i limiti di richiesta per un valore arbitrario. Ad esempio, potresti permettere agli utenti di accedere a una determinata rotta 100 volte al minuto per indirizzo IP. Per fare ciò, puoi usare il metodo by
quando definisci il limite di richiesta:
RateLimiter::for('uploads', function (Request $request) {
return $request->user()->vipCustomer()
? Limit::none()
: Limit::perMinute(100)->by($request->ip());
});
Per illustrare questa funzionalità con un altro esempio, possiamo limitare l’accesso alla rotta a 100 volte al minuto per ID utente autenticato o a 10 volte al minuto per indirizzo IP per gli ospiti:
RateLimiter::for('uploads', function (Request $request) {
return $request->user()
? Limit::perMinute(100)->by($request->user()->id)
: Limit::perMinute(10)->by($request->ip());
});
Limiti multipli
Se necessario, puoi restituire un array di limiti per una determinata configurazione di rate limiter. Ogni limite di frequenza sarà valutato per la rotta in base all’ordine in cui sono inseriti nell’array:
RateLimiter::for('login', function (Request $request) {
return [
Limit::perMinute(500),
Limit::perMinute(3)->by($request->input('email')),
];
});
Se stai assegnando più limiti di frequenza segmentati da valori by
identici, dovresti assicurarti che ogni valore by
sia unico. Il modo più semplice per ottenere ciò è anteporre un prefisso ai valori passati al metodo by
:
RateLimiter::for('uploads', function (Request $request) {
return [
Limit::perMinute(10)->by('minute:'.$request->user()->id),
Limit::perDay(1000)->by('day:'.$request->user()->id),
];
});
Assegnare i Rate Limiter alle Rotte
I rate limiter possono essere assegnati alle rotte o ai gruppi di rotte utilizzando il middleware throttle
. Il middleware throttle accetta il nome del rate limiter che vuoi assegnare alla rotta:
Route::middleware(['throttle:uploads'])->group(function () {
Route::post('/audio', function () {
// ...
});
Route::post('/video', function () {
// ...
});
});
Throttling con Redis
Di default, il middleware throttle
è associato alla classe Illuminate\Routing\Middleware\ThrottleRequests
. Tuttavia, se stai usando Redis come driver di cache della tua applicazione, potresti voler istruire Laravel ad usare Redis per gestire il rate limiting. Per fare ciò, dovresti usare il metodo throttleWithRedis
nel file bootstrap/app.php
della tua applicazione. Questo metodo associa il middleware throttle
alla classe middleware Illuminate\Routing\Middleware\ThrottleRequestsWithRedis
:
->withMiddleware(function (Middleware $middleware) {
$middleware->throttleWithRedis();
// ...
})
Workaround per i Metodi dei Form
I form HTML non supportano le azioni PUT
, PATCH
o DELETE
. Quindi, quando definisci rotte PUT
, PATCH
o DELETE
che vengono chiamate da un form HTML, devi aggiungere un campo nascosto _method
al form. Il valore inviato con il campo _method
verrà usato come metodo della richiesta HTTP:
<form action="/example" method="POST">
<input type="hidden" name="_method" value="PUT">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
</form>
Per comodità, puoi usare la direttiva @method
Blade directive per generare il campo di input _method
:
<form action="/example" method="POST">
@method('PUT')
@csrf
</form>
Accesso alla Rotta Attuale
Puoi usare i metodi current
, currentRouteName
e currentRouteAction
sulla facade Route
per accedere alle informazioni sulla rotta che sta gestendo la richiesta in arrivo:
use Illuminate\Support\Facades\Route;
$route = Route::current(); // Illuminate\Routing\Route
$name = Route::currentRouteName(); // string
$action = Route::currentRouteAction(); // string
Puoi consultare la documentazione API sia per la classe di base della facade Route sia per l’istanza Route per vedere tutti i metodi disponibili nelle classi del router e della rotta.
Cross-Origin Resource Sharing (CORS)
Laravel può rispondere automaticamente alle richieste HTTP OPTIONS
di CORS con i valori che configuri. Le richieste OPTIONS
vengono gestite automaticamente dal middleware HandleCors
middleware incluso nello stack globale dei middleware della tua applicazione.
A volte, potresti dover personalizzare i valori di configurazione CORS per la tua applicazione. Puoi farlo pubblicando il file di configurazione cors
usando il comando Artisan config:publish
:
php artisan config:publish cors
Questo comando creerà un file di configurazione cors.php
nella directory config
della tua applicazione.
Per ulteriori informazioni su CORS e sugli header CORS, consulta la documentazione web MDN su CORS.
Cache delle Route
Quando distribuisci la tua applicazione in produzione, dovresti approfittare della cache delle route di Laravel. Usare la cache delle route ridurrà drasticamente il tempo necessario per registrare tutte le route della tua applicazione. Per generare una cache delle route, esegui il comando Artisan route:cache
:
php artisan route:cache
Dopo aver eseguito questo comando, il file delle route cache verrà caricato ad ogni richiesta. Ricorda, se aggiungi nuove route dovrai generare una nuova cache delle route. Per questo motivo, dovresti eseguire il comando route:cache
solo durante il deploy del tuo progetto.
Puoi usare il comando route:clear
per svuotare la cache delle route:
php artisan route:clear