Vai al contenuto principale
A volte vuoi aggiungere l’autorizzazione ai modelli forniti da un pacchetto lasciando però all’applicazione che lo usa la possibilità di sostituirla con regole proprie. Se dichiari esplicitamente la corrispondenza tra modello e Policy e valuti l’utente solo nel momento in cui esegui l’autorizzazione, separi la registrazione dalle decisioni prese a ogni richiesta. Questa pagina fa riferimento al branch predefinito 13.x della documentazione ufficiale di Laravel e all’implementazione e ai test ufficiali dell’ultima release di Framework, v13.42.0, verificati il 10 novembre 2026. Per le basi dell’autorizzazione consulta la guida all’autorizzazione, per il caricamento dei provider consulta auto-discovery dei pacchetti.

Non dipendere dalla classe User dell’applicazione

Come esempio, aggiungiamo l’autorizzazione update al modello Acme\Reports\Models\Report del pacchetto. Si presuppone che la tabella acme_reports abbia una colonna owner_id che memorizza l’identificativo di autenticazione del proprietario. Come fornire le migration è spiegato in migration dei pacchetti. src/Models/Report.php è un normale modello Eloquent.
Se la Policy del pacchetto tipizza App\Models\User, dipende dal namespace e dalla struttura dei modelli dell’applicazione. Se ti serve solo l’identificativo di autenticazione dell’utente, usa il contratto Authenticatable di Laravel. Inserisci quanto segue in src/Policies/ReportPolicy.php.
Prima si escludono gli identificativi null, poi la differenza di tipo tra un intero letto dal database e una stringa viene assorbita confrontando entrambi come stringhe. In questo esempio solo il proprietario può aggiornare. Nelle applicazioni con più tipi di utente o più guard, verifica anche che l’identificativo da solo basti a individuare il soggetto in modo univoco. Se non basta, sostituiscila con una Policy propria che includa i confini di tipo di utente o di tenant.
Authenticatable è un contratto per dati come l’identificativo di autenticazione. Non fornisce isAdministrator() né metodi per ottenere i ruoli. Se ti servono informazioni sui permessi specifiche del pacchetto, definisci un contratto separato e lascia che l’applicazione inietti un’implementazione.

Registrare la corrispondenza nel service provider

Nel boot() di src/ReportsServiceProvider.php, registra solo i modelli che appartengono al pacchetto.
Gate::policy() salva il nome della classe della Policy usando come chiave il nome della classe del modello. La registrazione in sé non crea la Policy, non interroga il database e non valuta alcun utente. La Policy viene creata con make() del container quando serve, ad esempio in Gate::getPolicyFor(). Per questo puoi iniettare dipendenze nel costruttore della Policy. La posizione di Report e ReportPolicy è compatibile anche con l’auto-discovery standard, ma qui la registrazione è esplicita per rendere chiara la corrispondenza fornita dal pacchetto. La sola registrazione non applica l’autorizzazione agli endpoint HTTP. Prima dell’aggiornamento, chiama quanto segue, ad esempio in un controller.
In caso di rifiuto viene lanciata una AuthorizationException, che la normale gestione HTTP trasforma in una risposta 403. Gli argomenti del metodo della Policy sono diversi tra update, che riceve un modello, e abilità come create, che ricevono il nome della classe del modello. Segui le modalità di chiamata della guida all’autorizzazione.

Leggere l’ordine di risoluzione delle Policy

Gate::getPolicyFor() converte un oggetto nel suo nome di classe e cerca nell’ordine seguente. Questo è l’ordine di scelta della Policy, non l’ordine di esecuzione di tutti gli hook di autorizzazione. Quindi, finché esiste una registrazione esplicita per la stessa classe Report, modificare solo #[UsePolicy] o la convenzione dei nomi non la sostituisce. Se invece l’applicazione usa un modello che estende Report, la Policy trovata tramite l’attributo della classe figlia o la deduzione ha la precedenza sulla registrazione esplicita del padre. Verifica anche con la classe di modello effettivamente usata.
guessPolicyNamesUsing() non aggiunge un callback a una lista, ma sostituisce l’unico callback di deduzione del Gate. Se un pacchetto indipendente lo imposta solo per i propri modelli, influisce anche sulla deduzione dell’applicazione e degli altri pacchetti. Usa come base la registrazione con policy() dei modelli che appartengono al pacchetto.

Eseguire l’override esplicito nell’applicazione

Se richiami policy() per lo stesso modello, la registrazione successiva sostituisce la corrispondenza. Metterla semplicemente nel boot() di un altro provider dipende dall’ordine di caricamento, quindi una possibilità è registrare un callback di avvio completato da AppServiceProvider::boot() dell’applicazione.
ApplicationReportPolicy è una Policy implementata dall’applicazione. Se il pacchetto registra in un normale boot(), questo callback viene eseguito dopo. Non è un meccanismo che ha la precedenza in modo incondizionato, nemmeno rispetto a nuove registrazioni in altri callback booted o a provider caricati successivamente. In questo esempio il provider di registrazione del pacchetto non è un provider differito. In alternativa, puoi lasciare invariata la corrispondenza e sostituire nel container la destinazione di risoluzione di ReportPolicy::class. resolvePolicy() chiede ogni volta la risoluzione al container, ma se si ottiene davvero una nuova istanza dipende dal binding della Policy. Evita design che leggono informazioni sull’utente o sulla richiesta nel costruttore e le conservano in una Policy singleton.

Separare gli hook che influiscono su tutta l’autorizzazione

In un normale controllo del Gate, il Gate::before() globale viene eseguito per primo. Se restituisce un valore diverso da null, la valutazione della Policy non viene eseguita. Il diagramma mostra solo il percorso in cui viene trovata una Policy e il metodo corrispondente può essere chiamato. Omette gli hook after globali successivi e il fallback alle definizioni del Gate quando la Policy non ha il metodo target. Non registrare un Gate::before() globale che consenta tutte le abilità solo per gestire gli amministratori nel pacchetto. Consentiresti anche l’autorizzazione di altri pacchetti e dell’applicazione. Un before() all’interno della Policy vale solo per quella Policy, ma non viene chiamato se manca il metodo per l’abilità. Se vuoi che decida il metodo successivo, restituisci null invece di false. Inoltre, update() in questo esempio richiede un Authenticatable non nullable, quindi il metodo della Policy non viene eseguito per gli ospiti. Se nessun hook globale sovrascrive il risultato, la richiesta viene rifiutata. Per consentire gli ospiti, ad esempio per una consultazione pubblica, prevedi separatamente un argomento utente nullable e una verifica esplicita.

Testare separatamente registrazione e valutazione

Si presuppone la classe base di Testbench presentata in test dei pacchetti, con ReportsServiceProvider::class caricato in getPackageProviders(). Quello che segue è un esempio di tests/Feature/ReportPolicyTest.php. Per gli utenti si usa il modello di autenticazione generico di Laravel, così puoi valutare senza salvare nel database.
forUser() non riscrive l’utente del Gate condiviso. Crea un Gate separato passando le corrispondenze, le abilità e i callback di quel momento. Di conseguenza, un Gate per utente già creato non riflette le successive modifiche alle registrazioni delle Policy sul Gate condiviso. Completa le registrazioni all’avvio e non salvare Gate per utente in servizi di lunga durata. Nell’applicazione servono anche verifiche con il guard e il modello utente reali e test HTTP sull’endpoint di aggiornamento. I test precedenti da soli non verificano che l’autorizzazione sia applicata alla route né il formato con cui l’identificativo del proprietario è salvato nel database.

Contratti da mantenere negli aggiornamenti

  • I risultati per proprietario, non proprietari, ospiti e record senza proprietario sono invariati?
  • I nomi delle abilità pubblicate corrispondono agli argomenti dei metodi della Policy?
  • La sostituzione della Policy da parte dell’applicazione funziona ancora?
  • Se supporti modelli figli, la Policy effettivamente selezionata per la classe figlia è corretta?
  • Le richieste di aggiornamento reali vengono consentite e rifiutate come previsto, compresi gli hook globali dell’applicazione?
Gli aggiornamenti che rimuovono abilità esistenti o cambiano il comportamento predefinito di consenso o rifiuto influiscono sulle applicazioni. Insieme alla gestione della compatibilità delle versioni, tratta anche le modifiche all’autorizzazione come un contratto pubblico.

Fonti primarie consultate

Ultima modifica il 10 novembre 2026