はじめに
Laravelは、組み込みの認証サービスを提供するだけでなく、特定のリソースに対するユーザーアクションの承認を簡単に行う方法も提供しています。たとえば、ユーザーが認証されている場合でも、アプリケーションによって管理されている特定のEloquentモデルやデータベースレコードを更新または削除する権限がない場合があります。Laravelの承認機能は、これらの種類の承認チェックを管理するための簡単で整理された方法を提供します。
Laravelは、アクションを承認するための2つの主要な方法を提供します:ゲートとポリシー。ゲートとポリシーは、ルートとコントローラーのようなものと考えてください。ゲートは、承認に対するシンプルでクロージャベースのアプローチを提供し、ポリシーはコントローラーのように、特定のモデルやリソースに関連するロジックをグループ化します。このドキュメントでは、まずゲートを探求し、その後ポリシーを検討します。
アプリケーションを構築する際に、ゲートを独占的に使用するか、ポリシーを独占的に使用するかを選択する必要はありません。ほとんどのアプリケーションには、ゲートとポリシーの混合が含まれる可能性が高く、それは全く問題ありません!ゲートは、管理者ダッシュボードの表示など、モデルやリソースに関連しないアクションに最も適用されます。それに対して、ポリシーは特定のモデルやリソースに対するアクションを承認したい場合に使用するべきです。
ゲート
ゲートの作成
ゲートは、Laravelの承認機能の基本を学ぶための素晴らしい方法ですが、堅牢なLaravelアプリケーションを構築する際には、承認ルールを整理するためにポリシーを使用することを検討すべきです。
ゲートは、ユーザーが特定のアクションを実行する権限があるかどうかを判断するクロージャです。通常、ゲートはboot
メソッド内でApp\Providers\AppServiceProvider
クラスを使用して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']);
}
アクションの承認
ゲートを使用してアクションを承認するには、allows
またはdenies
メソッドをGate
ファサードから使用する必要があります。これらのメソッドに現在認証されているユーザーを渡す必要はありません。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');
}
}
現在認証されているユーザー以外のユーザーがアクションを実行する権限があるかどうかを判断したい場合は、forUser
メソッドをGate
ファサードで使用できます:
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...
}
``````php
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
)は、第二引数として配列を受け取ることができます。これらの配列要素は、ゲートクロージャにパラメータとして渡され、承認決定を行う際の追加のコンテキストとして使用できます:
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();
}
アクションが承認されていない場合にAuthorizationException
をスローするGate::authorize
メソッドを使用する場合、承認レスポンスによって提供されたエラーメッセージはHTTPレスポンスに伝播されます:
Gate::authorize('edit-settings');
// The action is authorized...
HTTPレスポンスステータスのカスタマイズ
アクションがゲートによって拒否された場合、403
HTTPレスポンスが返されます。ただし、失敗した承認チェックに対して代替のHTTPステータスコードを返すことが有用な場合があります。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
レスポンスで隠すことは、Webアプリケーションにとって一般的なパターンであるため、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;
}
});
`````after`````メソッドを使用して、すべての他の承認チェックの後に実行されるクロージャを定義できます:
``````php
use App\Models\User;
Gate::after(function (User $user, string $ability, bool|null $result, mixed $arguments) {
if ($user->isAdministrator()) {
return true;
}
});
`
<a name="inline-authorization"></a>
### 認証
- [はじめに](#introduction)
- [ゲート](#gates)
- [ゲートの作成](#writing-gates)
- [アクションの認可](#authorizing-actions-via-gates)
- [ゲートの応答](#gate-responses)
- [ゲートチェックのインターセプト](#intercepting-gate-checks)
- [インライン認可](#inline-authorization)
- [ポリシーの作成](#creating-policies)
- [ポリシーの生成](#generating-policies)
- [ポリシーの登録](#registering-policies)
- [ポリシーの作成](#writing-policies)
- [ポリシーメソッド](#policy-methods)
- [ポリシーの応答](#policy-responses)
- [モデルなしのメソッド](#methods-without-models)
- [ゲストユーザー](#guest-users)
- [ポリシーフィルター](#policy-filters)
- [ポリシーを使用したアクションの認可](#authorizing-actions-using-policies)
- [ユーザーモデルを介して](#via-the-user-model)
- [ゲートファサードを介して](#via-the-gate-facade)
- [ミドルウェアを介して](#via-middleware)
- [Bladeテンプレートを介して](#via-blade-templates)
- [追加のコンテキストを提供する](#supplying-additional-context)
- [認可とイナーシャ](#authorization-and-inertia)
<a name="introduction"></a>
## ポリシーの作成
<a name="generating-policies"></a>
### ポリシーの生成
ポリシーは、特定のモデルまたはリソースに関する認可ロジックを整理するクラスです。たとえば、アプリケーションがブログである場合、`````App\Models\Post`````モデルと、投稿の作成や更新などのユーザーアクションを認可するための対応する`````App\Policies\PostPolicy`````があるかもしれません。
ポリシーは、`````make:policy````` Artisanコマンドを使用して生成できます。生成されたポリシーは、`````app/Policies`````ディレクトリに配置されます。このディレクトリがアプリケーションに存在しない場合、Laravelは自動的に作成します:
``````shell
php artisan make:policy PostPolicy
`
``````shell
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...
});
ポリシーの手動登録
``````php
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);
}
`
ポリシーの作成
ポリシーメソッド
ポリシークラスが登録されると、そのポリシーが承認する各アクションのためのメソッドを追加できます。たとえば、update
メソッドをPostPolicy
に定義し、特定のApp\Models\User
が特定のApp\Models\Post
インスタンスを更新できるかどうかを判断します。
``````php
<?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;
}
}
`
ポリシーが承認するさまざまなアクションに必要に応じて、追加のメソッドを定義し続けることができます。たとえば、view
やdelete
メソッドを定義して、さまざまなPost
関連のアクションを承認することができますが、ポリシーメソッドに任意の名前を付けることができます。
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();
}
アクションが承認されていない場合にAuthorizationException
をスローするGate::authorize
メソッドを使用する場合、承認レスポンスによって提供されたエラーメッセージはHTTPレスポンスに伝播されます:
Gate::authorize('update', $post);
// The action is authorized...
HTTPレスポンスステータスのカスタマイズ
ポリシーメソッドによってアクションが拒否された場合、403
HTTPレスポンスが返されます。ただし、失敗した承認チェックに対して代替のHTTPステータスコードを返すことが有用な場合があります。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
レスポンスで隠すことは、Webアプリケーションにとって一般的なパターンであるため、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
を自動的に返します。ただし、オプションの型ヒントを宣言するか、ユーザー引数定義に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;
}
特定のタイプのユーザーに対してすべての承認チェックを拒否したい場合は、false
をbefore
メソッドから返すことができます。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
メソッドは、指定されたアクション名に一致するクロージャベースのゲートを呼び出そうとします。
モデルを必要としないアクション
覚えておいてください、一部のアクションは、モデルインスタンスを必要としないポリシーメソッドに対応する場合があります。これらの状況では、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');
}
}
ゲートファサード経由
`````can`````メソッドと同様に、このメソッドは、承認したいアクションの名前と関連するモデルを受け取ります。アクションが承認されていない場合、`````authorize`````メソッドは`````Illuminate\Auth\Access\AuthorizationException`````例外をスローし、Laravelの例外ハンドラーは自動的に403ステータスコードのHTTPレスポンスに変換します:
``````php
<?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
ミドルウェアは、can
ミドルウェアエイリアスを使用してルートに添付できます。これはLaravelによって自動的に登録されます。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つの引数を渡しています。最初は、承認したいアクションの名前で、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
追加のコンテキストの提供
ポリシーを使用してアクションを承認する際、さまざまな承認関数やヘルパーに第二引数として配列を渡すことができます。配列の最初の要素は、どのポリシーを呼び出すべきかを決定するために使用され、配列の残りの要素はポリシーメソッドにパラメータとして渡され、承認決定を行う際の追加のコンテキストとして使用できます。たとえば、次のPostPolicy
メソッド定義を考えてみましょう。これは追加の$category
パラメータを含んでいます:
/**
* 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),
],
],
],
];
}
}