メインコンテンツまでスキップ

認可

はじめに

Laravelは組み込みの認証サービスを提供するだけでなく、特定のリソースに対するユーザーアクションの認可を簡単に行う方法を提供します。たとえば、ユーザーが認証されていても、特定のEloquentモデルやアプリケーションが管理するデータベースレコードを更新または削除する権限がない場合があります。Laravelの認可機能は、この種の認可チェックを簡単かつ整理された方法で管理する手段を提供します。

Laravelには、アクションを認可するための主要な方法が2つあります:ゲートポリシー。ゲートとポリシーは、ルートとコントローラーのように考えることができます。ゲートは、クロージャベースのシンプルな認可アプローチを提供し、ポリシーは、コントローラーのように、特定のモデルやリソースにロジックをグループ化します。このドキュメントでは、まずゲートを探求し、その後にポリシーを検討します。

アプリケーションを構築する際に、ゲートのみを使用するか、ポリシーのみを使用するかを選択する必要はありません。ほとんどのアプリケーションは、おそらくゲートとポリシーの混合物を含むでしょうが、それは完全に問題ありません!ゲートは、モデルやリソースに関連しないアクションに最も適しており、管理者ダッシュボードを表示するなどの場合に使用されます。一方、特定のモデルやリソースのアクションを認可する場合は、ポリシーを使用する必要があります。

ゲート

ゲートの書き方

警告

ゲートは、Laravelの認可機能の基本を学ぶための素晴らしい方法です。ただし、堅牢なLaravelアプリケーションを構築する際には、認可ルールを整理するためにpoliciesを使用することを検討する必要があります。

ゲートは、ユーザーが特定のアクションを実行する権限があるかどうかを決定する単なるクロージャです。通常、ゲートは、Gateファサードを使用してApp\Providers\AppServiceProviderクラスのbootメソッド内で定義されます。ゲートは常にユーザーインスタンスを最初の引数として受け取り、関連する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...

追加のコンテキストの提供

アビリティを認可するためのゲートメソッド(allowsdeniescheckanynoneauthorizecancannot)および認可の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();
}

アクションが認可されていない場合に403のHTTPレスポンスが返されるゲートを使用する場合、認可レスポンスによって提供されるエラーメッセージがHTTPレスポンスに伝播されます:

    Gate::authorize('edit-settings');

// The action is authorized...

HTTPレスポンスステータスのカスタマイズ

Gateを介してアクションが拒否されると、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);
});

Webアプリケーションでリソースを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;
}
});

before メソッドと同様に、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メソッドを使用してカスタムポリシー検出コールバックを登録することができます。通常、このメソッドはアプリケーションのAppServiceProviderbootメソッドから呼び出すべきです:

    use Illuminate\Support\Facades\Gate;

Gate::guessPolicyNamesUsing(function (string $modelClass) {
// Return the name of the policy class for the given model...
});

ポリシーの手動登録

Gateファサードを使用して、アプリケーションのAppServiceProviderbootメソッド内でポリシーとそれに対応するモデルを手動で登録することができます:

    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);
}

ポリシーの記述

ポリシーメソッド

ポリシークラスが登録されると、そのクラスが承認する各アクションのためのメソッドを追加することができます。例えば、PostPolicyupdateメソッドを定義して、与えられたApp\Models\Userが与えられたApp\Models\Postインスタンスを更新できるかどうかを判断します。

updateメソッドは、UserPostインスタンスを引数として受け取り、与えられた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;
}
}

必要に応じてポリシーに追加のメソッドを定義することができます。たとえば、さまざまなアクションを承認するために viewdelete メソッドを定義することができますが、ポリシーメソッドには任意の名前を付けることができることを覚えておいてください。

Artisan コンソールを介してポリシーを生成する際に --model オプションを使用した場合、viewAnyviewcreateupdatedeleterestoreforceDelete アクション用のメソッドが既に含まれています。

注記

すべてのポリシーは 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();
}

アクションが承認されていない場合に 403 HTTP レスポンスが返されますが、アクションが承認されていない場合に AuthorizationException をスローする Gate::authorize メソッドを使用すると、認可レスポンスによって提供されるエラーメッセージが 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レスポンスは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を返します。ただし、"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つの便利なメソッド、cancannot が含まれています。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 メソッドは指定されたアクション名に一致するクロージャベースのGateを呼び出そうとします。

モデルを必要としないアクション

いくつかのアクションは、モデルインスタンスを必要としない 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 つの引数を渡しています。最初の引数は認可したいアクションの名前であり、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 ディレクティブを使用できます:

これらのディレクティブは、@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引数として配列を渡すことができます。配列の最初の要素は、どのポリシーを呼び出すかを決定するために使用され、残りの配列要素はポリシーメソッドに渡され、認可の決定時に追加のコンテキストとして使用できます。たとえば、次の 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),
],
],
],
];
}
}