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’autorizzazioneupdate 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.
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.
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
Nelboot() 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.
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.
Eseguire l’override esplicito nell’applicazione
Se richiamipolicy() 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, ilGate::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, conReportsServiceProvider::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?
Fonti primarie consultate
- Documentazione ufficiale di Laravel: Autorizzazione
- Documentazione ufficiale di Laravel: Sviluppo di pacchetti
- Framework v13.42.0: registrazione, risoluzione e forUser del Gate
- Framework v13.42.0: AuthServiceProvider, che registra il Gate come singleton
- Framework v13.42.0: boot e booted di Application
- Framework v13.42.0: test ufficiali del Gate di autorizzazione