承認
導入
Laravelは組み込みの認証サービスを提供することに加えて、特定のリソースに対するユーザーアクションを承認する簡単な方法も提供します。例えば、ユーザーが認証されている場合でも、アプリケーションによって管理されている特定のEloquentモデルやデータベースレコードの更新または削除を承認されていない場合があります。Laravelの承認機能は、このような種類の承認チェックを簡単に整理して管理する方法を提供します。
Laravelは、アクションを承認する2つの主要な方法を提供します。 ゲートとポリシーです。ゲートとポリシーは、ルートとコントローラーのようなものと考えてください。ゲートは、承認に対するシンプルでクロージャーベースのアプローチを提供する一方、ポリシーはコントローラーのように、特定のモデルまたはリソースに関するロジックをグループ化します。このドキュメントでは、最初にゲートを説明し、次にポリシーについて説明します。
アプリケーションを構築する際に、ゲートのみを使用するか、ポリシーのみを使用するかを選択する必要はありません。ほとんどのアプリケーションは、ゲートとポリシーを組み合わせて使用することになるでしょうし、それは全く問題ありません!ゲートは、管理者ダッシュボードの表示など、モデルやリソースに関連しないアクションに最も適しています。一方、ポリシーは、特定のモデルまたはリソースに対するアクションを承認する場合に使用すべきです。
ゲート
ゲートの作成
ゲートはLaravelの承認機能の基本を学ぶための優れた方法ですが、堅牢なLaravelアプリケーションを構築する際には、ポリシーを使用して承認ルールを整理することを検討する必要があります。
ゲートは、ユーザーが特定のアクションを実行する権限があるかどうかを判断するクロージャーです。通常、ゲートは`App\Providers\AppServiceProvider`クラスの`boot`メソッド内で、`Gate`ファサードを使用して定義されます。ゲートは常に最初の引数としてユーザーインスタンスを受け取り、関連するEloquentモデルなどの追加の引数を受け取ることもできます。
この例では、ユーザーが特定の`App\Models\Post`モデルを更新できるかどうかを判断するゲートを定義します。このゲートは、ユーザーの`id`と投稿を作成したユーザーの`user_id`を比較することでこれを実現します。
use App\Models\Post;use App\Models\User;use Illuminate\Support\Facades\Gate; /** * Bootstrap any application services. */public function boot(): void{ Gate::define('update-post', function (User $user, Post $post) { return $user->id === $post->user_id; });}
コントローラーと同様に、ゲートもクラスコールバック配列を使用して定義できます。
use App\Policies\PostPolicy;use Illuminate\Support\Facades\Gate; /** * Bootstrap any application services. */public function boot(): void{ Gate::define('update-post', [PostPolicy::class, 'update']);}
アクションの承認
ゲートを使用してアクションを承認するには、`Gate`ファサードによって提供される`allows`または`denies`メソッドを使用する必要があります。これらのメソッドに現在認証されているユーザーを渡す必要はありません。Laravelは、ユーザーをゲートクロージャーに自動的に渡します。ゲート承認メソッドは、承認が必要なアクションを実行する前に、アプリケーションのコントローラー内で呼び出すのが一般的です。
<?php namespace App\Http\Controllers; use App\Http\Controllers\Controller;use App\Models\Post;use Illuminate\Http\RedirectResponse;use Illuminate\Http\Request;use Illuminate\Support\Facades\Gate; class PostController extends Controller{ /** * Update the given post. */ public function update(Request $request, Post $post): RedirectResponse { if (! Gate::allows('update-post', $post)) { abort(403); } // Update the post... return redirect('/posts'); }}
現在認証されているユーザー以外のユーザーがアクションを実行する権限があるかどうかを確認したい場合は、`Gate`ファサードの`forUser`メソッドを使用できます。
if (Gate::forUser($user)->allows('update-post', $post)) { // The user can update the post...} if (Gate::forUser($user)->denies('update-post', $post)) { // The user can't update the post...}
`any`または`none`メソッドを使用して、一度に複数の操作を承認できます。
if (Gate::any(['update-post', 'delete-post'], $post)) { // The user can update or delete the post...} if (Gate::none(['update-post', 'delete-post'], $post)) { // The user can't update or delete the post...}
承認または例外の発生
アクションを承認しようとして、ユーザーが特定のアクションを実行することを許可されていない場合に`Illuminate\Auth\Access\AuthorizationException`を自動的にスローしたい場合は、`Gate`ファサードの`authorize`メソッドを使用できます。`AuthorizationException`のインスタンスは、Laravelによって自動的に403 HTTPレスポンスに変換されます。
Gate::authorize('update-post', $post); // The action is authorized...
追加コンテキストの提供
能力を承認するためのゲートメソッド(`allows`、`denies`、`check`、`any`、`none`、`authorize`、`can`、`cannot`)と承認Bladeディレクティブ(`@can`、`@cannot`、`@canany`)は、2番目の引数として配列を受け取ることができます。これらの配列要素は、ゲートクロージャーのパラメーターとして渡され、承認の決定を行う際の追加コンテキストに使用できます。
use App\Models\Category;use App\Models\User;use Illuminate\Support\Facades\Gate; Gate::define('create-post', function (User $user, Category $category, bool $pinned) { if (! $user->canPublishToGroup($category->group)) { return false; } elseif ($pinned && ! $user->canPinPosts()) { return false; } return true;}); if (Gate::check('create-post', [$category, $pinned])) { // The user can create the post...}
ゲートレスポンス
これまでのところ、単純なブール値を返すゲートしか見ていません。しかし、場合によっては、エラーメッセージを含むより詳細なレスポンスを返したい場合があります。そのためには、ゲートから`Illuminate\Auth\Access\Response`を返すことができます。
use App\Models\User;use Illuminate\Auth\Access\Response;use Illuminate\Support\Facades\Gate; Gate::define('edit-settings', function (User $user) { return $user->isAdmin ? Response::allow() : Response::deny('You must be an administrator.');});
ゲートから承認レスポンスを返した場合でも、`Gate::allows`メソッドは単純なブール値を返します。ただし、`Gate::inspect`メソッドを使用して、ゲートによって返される完全な承認レスポンスを取得できます。
$response = Gate::inspect('edit-settings'); if ($response->allowed()) { // The action is authorized...} else { echo $response->message();}
`Gate::authorize`メソッドを使用する場合(アクションが承認されていない場合、`AuthorizationException`をスローします)、承認レスポンスによって提供されるエラーメッセージはHTTPレスポンスに伝達されます。
Gate::authorize('edit-settings'); // The action is authorized...
HTTPレスポンスステータスのカスタマイズ
ゲートを介してアクションが拒否された場合、`403` HTTPレスポンスが返されます。ただし、代替のHTTPステータスコードを返すことが役立つ場合があります。`Illuminate\Auth\Access\Response`クラスの`denyWithStatus`静的コンストラクターを使用して、失敗した認証チェックに対して返されるHTTPステータスコードをカスタマイズできます。
use App\Models\User;use Illuminate\Auth\Access\Response;use Illuminate\Support\Facades\Gate; Gate::define('edit-settings', function (User $user) { return $user->isAdmin ? Response::allow() : Response::denyWithStatus(404);});
`404`レスポンスを介してリソースを隠すことは、ウェブアプリケーションでは非常に一般的なパターンであるため、便宜上`denyAsNotFound`メソッドが提供されています。
use App\Models\User;use Illuminate\Auth\Access\Response;use Illuminate\Support\Facades\Gate; Gate::define('edit-settings', function (User $user) { return $user->isAdmin ? Response::allow() : Response::denyAsNotFound();});
ゲートチェックのインターセプト
特定のユーザーにすべての権限を付与したい場合があります。`before`メソッドを使用して、他のすべての認証チェックの前に実行されるクロージャーを定義できます。
use App\Models\User;use Illuminate\Support\Facades\Gate; Gate::before(function (User $user, string $ability) { if ($user->isAdministrator()) { return true; }});
`before`クロージャーがNULL以外の結果を返す場合、その結果は認証チェックの結果と見なされます。
`after`メソッドを使用して、他のすべての認証チェックの後で実行されるクロージャーを定義できます。
use App\Models\User; Gate::after(function (User $user, string $ability, bool|null $result, mixed $arguments) { if ($user->isAdministrator()) { return true; }});
after
クロージャによって返される値は、ゲートまたはポリシーがnull
を返す場合を除き、承認チェックの結果を上書きしません。
インライン認証
場合によっては、アクションに対応する専用のゲートを作成せずに、現在認証されているユーザーが特定のアクションを実行する権限を持っているかどうかを判断したい場合があります。Laravelでは、Gate::allowIf
メソッドとGate::denyIf
メソッドを使用して、このような「インライン」承認チェックを実行できます。インライン承認は、定義済みの「before」または「after」の承認フックを実行しません。
use App\Models\User;use Illuminate\Support\Facades\Gate; Gate::allowIf(fn (User $user) => $user->isAdministrator()); Gate::denyIf(fn (User $user) => $user->banned());
アクションが承認されていない場合、または現在認証されているユーザーがいない場合、Laravelは自動的にIlluminate\Auth\Access\AuthorizationException
例外をスローします。AuthorizationException
のインスタンスは、Laravelの例外ハンドラーによって自動的に403 HTTPレスポンスに変換されます。
ポリシーの作成
ポリシーの生成
ポリシーは、特定のモデルまたはリソースを中心とした承認ロジックを整理するクラスです。例えば、アプリケーションがブログの場合、App\Models\Post
モデルと、それに対応するApp\Policies\PostPolicy
を使用して、投稿の作成や更新などのユーザーアクションを承認できます。
make:policy
Artisanコマンドを使用してポリシーを生成できます。生成されたポリシーはapp/Policies
ディレクトリに配置されます。このディレクトリがアプリケーションに存在しない場合、Laravelによって作成されます。
php artisan make:policy PostPolicy
make:policy
コマンドは空のポリシークラスを生成します。リソースの表示、作成、更新、削除に関連する例となるポリシーメソッドを含むクラスを生成したい場合は、コマンドの実行時に--model
オプションを指定できます。
php artisan make:policy PostPolicy --model=Post
ポリシーの登録
ポリシーの自動検出
デフォルトでは、モデルとポリシーが標準のLaravel命名規則に従っている限り、Laravelはポリシーを自動的に検出します。具体的には、ポリシーは、モデルを含むディレクトリと同じレベルか、それより上のPolicies
ディレクトリに存在する必要があります。例えば、モデルをapp/Models
ディレクトリに配置し、ポリシーをapp/Policies
ディレクトリに配置する場合、Laravelはapp/Models/Policies
、次にapp/Policies
でポリシーをチェックします。さらに、ポリシー名はモデル名と一致し、Policy
サフィックスが付いている必要があります。したがって、User
モデルはUserPolicy
ポリシークラスに対応します。
独自のポリシー検出ロジックを定義する場合は、Gate::guessPolicyNamesUsing
メソッドを使用してカスタムポリシー検出コールバックを登録できます。通常、このメソッドはアプリケーションのAppServiceProvider
のboot
メソッドから呼び出されます。
use Illuminate\Support\Facades\Gate; Gate::guessPolicyNamesUsing(function (string $modelClass) { // Return the name of the policy class for the given model...});
ポリシーの手動登録
Gate
ファサードを使用して、アプリケーションのAppServiceProvider
のboot
メソッド内で、ポリシーとその対応するモデルを手動で登録できます。
use App\Models\Order;use App\Policies\OrderPolicy;use Illuminate\Support\Facades\Gate; /** * Bootstrap any application services. */public function boot(): void{ Gate::policy(Order::class, OrderPolicy::class);}
ポリシーの作成
ポリシーメソッド
ポリシークラスが登録されると、承認する各アクションのメソッドを追加できます。例えば、App\Models\User
が特定のApp\Models\Post
インスタンスを更新できるかどうかを判断するupdate
メソッドをPostPolicy
に定義してみましょう。
update
メソッドは、引数としてUser
とPost
インスタンスを受け取り、ユーザーが指定されたPost
を更新する権限があるかどうかを示すtrue
またはfalse
を返す必要があります。この例では、ユーザーのid
が投稿のuser_id
と一致するかどうかを確認します。
<?php namespace App\Policies; use App\Models\Post;use App\Models\User; class PostPolicy{ /** * Determine if the given post can be updated by the user. */ public function update(User $user, Post $post): bool { return $user->id === $post->user_id; }}
必要に応じて、承認するさまざまなアクションに対して、ポリシーにさらにメソッドを定義できます。例えば、さまざまなPost
関連のアクションを承認するためにview
メソッドやdelete
メソッドを定義できますが、ポリシーメソッドには任意の名前を付けることができます。
Artisanコンソールで--model
オプションを使用してポリシーを生成した場合、viewAny
、view
、create
、update
、delete
、restore
、forceDelete
アクションのメソッドが既に含まれています。
すべてのポリシーはLaravelのサービスコンテナを介して解決されるため、ポリシーのコンストラクタに必要な依存関係を型ヒントで指定すると、それらが自動的に注入されます。
ポリシーレスポンス
これまでのところ、単純なブール値を返すポリシーメソッドしか調べていません。しかし、エラーメッセージを含むより詳細なレスポンスを返す必要がある場合があります。そのためには、ポリシーメソッドからIlluminate\Auth\Access\Response
インスタンスを返すことができます。
use App\Models\Post;use App\Models\User;use Illuminate\Auth\Access\Response; /** * Determine if the given post can be updated by the user. */public function update(User $user, Post $post): Response{ return $user->id === $post->user_id ? Response::allow() : Response::deny('You do not own this post.');}
ポリシーから承認応答を返す場合、Gate::allows
メソッドは依然として単純なブール値を返しますが、Gate::inspect
メソッドを使用して、ゲートによって返された完全な承認応答を取得できます。
use Illuminate\Support\Facades\Gate; $response = Gate::inspect('update', $post); if ($response->allowed()) { // The action is authorized...} else { echo $response->message();}
`Gate::authorize`メソッドを使用する場合(アクションが承認されていない場合、`AuthorizationException`をスローします)、承認レスポンスによって提供されるエラーメッセージはHTTPレスポンスに伝達されます。
Gate::authorize('update', $post); // The action is authorized...
HTTPレスポンスステータスのカスタマイズ
ポリシーメソッドによってアクションが拒否されると、403
HTTPレスポンスが返されますが、代替のHTTPステータスコードを返す方が便利な場合があります。Illuminate\Auth\Access\Response
クラスのdenyWithStatus
静的コンストラクタを使用して、失敗した承認チェックに対して返されるHTTPステータスコードをカスタマイズできます。
use App\Models\Post;use App\Models\User;use Illuminate\Auth\Access\Response; /** * Determine if the given post can be updated by the user. */public function update(User $user, Post $post): Response{ return $user->id === $post->user_id ? Response::allow() : Response::denyWithStatus(404);}
`404`レスポンスを介してリソースを隠すことは、ウェブアプリケーションでは非常に一般的なパターンであるため、便宜上`denyAsNotFound`メソッドが提供されています。
use App\Models\Post;use App\Models\User;use Illuminate\Auth\Access\Response; /** * Determine if the given post can be updated by the user. */public function update(User $user, Post $post): Response{ return $user->id === $post->user_id ? Response::allow() : Response::denyAsNotFound();}
モデルを使用しないメソッド
一部のポリシーメソッドは、現在認証されているユーザーのインスタンスのみを受け取ります。これは、create
アクションを承認する場合に最も一般的です。例えば、ブログを作成する場合、ユーザーが投稿を作成できるかどうかを判断したい場合があります。このような場合、ポリシーメソッドはユーザーインスタンスのみを受け取る必要があります。
/** * Determine if the given user can create posts. */public function create(User $user): bool{ return $user->role == 'writer';}
ゲストユーザー
デフォルトでは、すべてのゲートとポリシーは、着信HTTPリクエストが認証済みユーザーによって開始されていない場合、自動的にfalse
を返します。ただし、「optional」型ヒントを宣言するか、ユーザー引数定義にnull
のデフォルト値を指定することで、これらの承認チェックをゲートとポリシーに渡すことができます。
<?php namespace App\Policies; use App\Models\Post;use App\Models\User; class PostPolicy{ /** * Determine if the given post can be updated by the user. */ public function update(?User $user, Post $post): bool { return $user?->id === $post->user_id; }}
ポリシーフィルター
特定のユーザーに対して、特定のポリシー内のすべてのアクションを承認したい場合があります。これを実現するには、ポリシーにbefore
メソッドを定義します。before
メソッドは、ポリシーの他のメソッドの前に実行され、目的のポリシーメソッドが実際に呼び出される前にアクションを承認する機会が得られます。この機能は、アプリケーション管理者が任意のアクションを実行することを承認する場合に最もよく使用されます。
use App\Models\User; /** * Perform pre-authorization checks. */public function before(User $user, string $ability): bool|null{ if ($user->isAdministrator()) { return true; } return null;}
特定の種類のユーザーのすべての承認チェックを拒否する場合は、before
メソッドからfalse
を返すことができます。null
が返された場合、承認チェックはポリシーメソッドに渡されます。
ポリシークラスのbefore
メソッドは、クラスがチェックされている能力の名前と一致する名前のメソッドを含まない場合は呼び出されません。
ポリシーを使用したアクションの承認
ユーザーモデル経由
Laravelアプリケーションに含まれるApp\Models\User
モデルには、アクションを承認するための2つの便利なメソッド(can
とcannot
)が含まれています。can
とcannot
メソッドは、承認するアクションの名前と関連するモデルを受け取ります。例えば、ユーザーが特定のApp\Models\Post
モデルを更新する権限があるかどうかを判断してみましょう。通常、これはコントローラーメソッド内で行われます。
<?php namespace App\Http\Controllers; use App\Http\Controllers\Controller;use App\Models\Post;use Illuminate\Http\RedirectResponse;use Illuminate\Http\Request; class PostController extends Controller{ /** * Update the given post. */ public function update(Request $request, Post $post): RedirectResponse { if ($request->user()->cannot('update', $post)) { abort(403); } // Update the post... return redirect('/posts'); }}
指定されたモデルに対してポリシーが登録されている場合、can
メソッドは適切なポリシーを自動的に呼び出し、ブール値の結果を返します。モデルに対してポリシーが登録されていない場合、can
メソッドは指定されたアクション名と一致するクロージャベースのゲートを呼び出そうとします。
モデルを必要としないアクション
一部のアクションは、モデルインスタンスを必要としないcreate
のようなポリシーメソッドに対応している場合があります。このような場合、can
メソッドにクラス名を渡すことができます。クラス名は、アクションを承認する際に使用するポリシーを決定するために使用されます。
<?php namespace App\Http\Controllers; use App\Http\Controllers\Controller;use App\Models\Post;use Illuminate\Http\RedirectResponse;use Illuminate\Http\Request; class PostController extends Controller{ /** * Create a post. */ public function store(Request $request): RedirectResponse { if ($request->user()->cannot('create', Post::class)) { abort(403); } // Create the post... return redirect('/posts'); }}
Gate
ファサードによる方法
App\Models\User
モデルに提供される便利なメソッドに加えて、常にGate
ファサードのauthorize
メソッドを使用してアクションを承認できます。
can
メソッドと同様に、このメソッドは承認するアクションの名前と関連するモデルを受け取ります。アクションが承認されていない場合、authorize
メソッドはIlluminate\Auth\Access\AuthorizationException
例外をスローします。Laravelの例外ハンドラーは、これを自動的に403ステータスコードのHTTPレスポンスに変換します。
<?php namespace App\Http\Controllers; use App\Http\Controllers\Controller;use App\Models\Post;use Illuminate\Http\RedirectResponse;use Illuminate\Http\Request;use Illuminate\Support\Facades\Gate; class PostController extends Controller{ /** * Update the given blog post. * * @throws \Illuminate\Auth\Access\AuthorizationException */ public function update(Request $request, Post $post): RedirectResponse { Gate::authorize('update', $post); // The current user can update the blog post... return redirect('/posts'); }}
モデルを必要としないアクション
前述のように、create
などの一部のポリシーメソッドはモデルインスタンスを必要としません。このような場合、クラス名をauthorize
メソッドに渡す必要があります。クラス名は、アクションを承認する際に使用するポリシーを決定するために使用されます。
use App\Models\Post;use Illuminate\Http\RedirectResponse;use Illuminate\Http\Request;use Illuminate\Support\Facades\Gate; /** * Create a new blog post. * * @throws \Illuminate\Auth\Access\AuthorizationException */public function create(Request $request): RedirectResponse{ Gate::authorize('create', Post::class); // The current user can create blog posts... return redirect('/posts');}
ミドルウェア経由
Laravelには、着信リクエストがルートやコントローラーに到達する前にアクションを承認できるミドルウェアが含まれています。デフォルトでは、Illuminate\Auth\Middleware\Authorize
ミドルウェアは、Laravelによって自動的に登録されるcan
ミドルウェアエイリアスを使用してルートにアタッチできます。ユーザーが投稿を更新できることを承認するためにcan
ミドルウェアを使用する例を見てみましょう。
use App\Models\Post; Route::put('/post/{post}', function (Post $post) { // The current user may update the post...})->middleware('can:update,post');
この例では、can
ミドルウェアに2つの引数を渡しています。1つ目は、承認するアクションの名前、2つ目はポリシーメソッドに渡すルートパラメーターです。ここでは暗黙的なモデルバインディングを使用しているため、App\Models\Post
モデルがポリシーメソッドに渡されます。ユーザーが指定されたアクションを実行する権限がない場合、ミドルウェアによって403ステータスコードのHTTPレスポンスが返されます。
便宜上、can
メソッドを使用してルートにcan
ミドルウェアをアタッチすることもできます。
use App\Models\Post; Route::put('/post/{post}', function (Post $post) { // The current user may update the post...})->can('update', 'post');
モデルを必要としないアクション
同様に、create
などの一部のポリシーメソッドはモデルインスタンスを必要としません。このような場合、ミドルウェアにクラス名を渡すことができます。クラス名は、アクションを承認する際に使用するポリシーを決定するために使用されます。
Route::post('/post', function () { // The current user may create posts...})->middleware('can:create,App\Models\Post');
文字列ミドルウェア定義内にクラス名を完全に指定すると煩雑になるため、can
メソッドを使用してルートにcan
ミドルウェアをアタッチすることを選択できます。
use App\Models\Post; Route::post('/post', function () { // The current user may create posts...})->can('create', Post::class);
Bladeテンプレート経由
Bladeテンプレートを作成する際には、ユーザーが特定のアクションを実行する権限がある場合にのみページの一部を表示したい場合があります。例えば、ユーザーが投稿を実際に更新できる場合にのみ、ブログ投稿の更新フォームを表示したい場合があります。このような場合、@can
ディレクティブと@cannot
ディレクティブを使用できます。
@can('update', $post) <!-- The current user can update the post... -->@elsecan('create', App\Models\Post::class) <!-- The current user can create new posts... -->@else <!-- ... -->@endcan @cannot('update', $post) <!-- The current user cannot update the post... -->@elsecannot('create', App\Models\Post::class) <!-- The current user cannot create new posts... -->@endcannot
これらのディレクティブは、@if
ステートメントと@unless
ステートメントを作成するための便利なショートカットです。上記の@can
ステートメントと@cannot
ステートメントは、次のステートメントと同等です。
@if (Auth::user()->can('update', $post)) <!-- The current user can update the post... -->@endif @unless (Auth::user()->can('update', $post)) <!-- The current user cannot update the post... -->@endunless
指定されたアクションの配列から、ユーザーが任意のアクションを実行する権限があるかどうかを判断することもできます。これを実現するには、@canany
ディレクティブを使用します。
@canany(['update', 'view', 'delete'], $post) <!-- The current user can update, view, or delete the post... -->@elsecanany(['create'], \App\Models\Post::class) <!-- The current user can create a post... -->@endcanany
モデルを必要としないアクション
他のほとんどの承認メソッドと同様に、アクションがモデルインスタンスを必要としない場合、クラス名を@can
ディレクティブと@cannot
ディレクティブに渡すことができます。
@can('create', App\Models\Post::class) <!-- The current user can create posts... -->@endcan @cannot('create', App\Models\Post::class) <!-- The current user can't create posts... -->@endcannot
追加コンテキストの提供
ポリシーを使用してアクションを承認する際、さまざまな承認関数およびヘルパーの第2引数として配列を渡すことができます。配列の最初の要素は、どのポリシーを呼び出すかを決定するために使用され、残りの配列要素はポリシーメソッドのパラメーターとして渡され、承認決定を行う際の追加のコンテキストとして使用できます。たとえば、追加の$category
パラメーターを含む次のPostPolicy
メソッド定義を考えてみましょう。
/** * Determine if the given post can be updated by the user. */public function update(User $user, Post $post, int $category): bool{ return $user->id === $post->user_id && $user->canUpdateCategory($category);}
認証済みユーザーが特定の投稿を更新できるかどうかを判断しようとすると、次のようにこのポリシーメソッドを呼び出すことができます。
/** * Update the given blog post. * * @throws \Illuminate\Auth\Access\AuthorizationException */public function update(Request $request, Post $post): RedirectResponse{ Gate::authorize('update', [$post, $request->category]); // The current user can update the blog post... return redirect('/posts');}
認証とInertia
承認は常にサーバーで処理する必要がありますが、フロントエンドアプリケーションに承認データを用意してアプリケーションのUIを適切にレンダリングすることが便利な場合があります。Laravelは、Inertia対応のフロントエンドに承認情報を公開するための必須の規約を定義していません。
ただし、LaravelのInertiaベースのスターターキットのいずれかを使用している場合、アプリケーションには既にHandleInertiaRequests
ミドルウェアが含まれています。このミドルウェアのshare
メソッド内で、アプリケーションのすべてのInertiaページに提供される共有データを返すことができます。この共有データは、ユーザーの承認情報を定義するための便利な場所として機能します。
<?php namespace App\Http\Middleware; use App\Models\Post;use Illuminate\Http\Request;use Inertia\Middleware; class HandleInertiaRequests extends Middleware{ // ... /** * Define the props that are shared by default. * * @return array<string, mixed> */ public function share(Request $request) { return [ ...parent::share($request), 'auth' => [ 'user' => $request->user(), 'permissions' => [ 'post' => [ 'create' => $request->user()->can('create', Post::class), ], ], ], ]; }}