Routing

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 e options dovrebbero essere definiti prima di quelli che usano i metodi any, match e redirect. 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 e status.

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 e headers.

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
Lascia un commento

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *