サイトを更新しています。 数日間、レイアウトや翻訳に不具合が出ることがあります。ドキュメントは引き続きご利用いただけます。表示が崩れている場合は、後ほど再読み込みしてください。

認可

10.x 2026年3月7日

#はじめに

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

Laravelには主に2つの認可方法があります:ゲートポリシーです。ゲートとポリシーはルートとコントローラーの関係に似ています。ゲートはシンプルなクロージャベースの認可方法を提供し、ポリシーはコントローラーのように特定のモデルやリソースに関連するロジックをまとめます。このドキュメントではまずゲートを説明し、その後ポリシーを解説します。

アプリケーション構築時にゲートだけ、またはポリシーだけを使う必要はありません。多くのアプリケーションではゲートとポリシーを組み合わせて使うことが多く、それで問題ありません。ゲートは管理者ダッシュボードの閲覧など、モデルやリソースに関連しないアクションに適しています。一方、特定のモデルやリソースに対するアクションを認可したい場合はポリシーを使うべきです。

#ゲート

#ゲートの作成

Внимание

ゲートはLaravelの認可機能の基本を学ぶのに最適ですが、堅牢なLaravelアプリケーションを構築する際は認可ルールを整理するためにポリシーの使用を検討してください。

ゲートはユーザーが特定のアクションを実行できるかどうかを判定するクロージャです。通常、App\Providers\AuthServiceProviderクラスのbootメソッド内でGateファサードを使って定義します。ゲートは常に最初の引数にユーザーインスタンスを受け取り、必要に応じて関連するEloquentモデルなどの追加引数も受け取れます。

この例では、ユーザーが特定のApp\Models\Postモデルを更新できるかどうかを判定するゲートを定義します。ユーザーのidと投稿を作成したユーザーのuser_idを比較して判定します:

use App\Models\Post;
use App\Models\User;
use Illuminate\Support\Facades\Gate;

/**
 * 認証/認可サービスを登録します。
 */
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;

/**
 * 認証/認可サービスを登録します。
 */
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
{
    /**
     * 指定された投稿を更新します。
     */
    public function update(Request $request, Post $post): RedirectResponse
    {
        if (! Gate::allows('update-post', $post)) {
            abort(403);
        }

        // 投稿を更新する処理...

        return redirect('/posts');
    }
}

現在認証されているユーザー以外のユーザーがアクションを実行できるか判定したい場合は、GateファサードのforUserメソッドを使います:

if (Gate::forUser($user)->allows('update-post', $post)) {
    // ユーザーは投稿を更新できます...
}

if (Gate::forUser($user)->denies('update-post', $post)) {
    // ユーザーは投稿を更新できません...
}

複数のアクションを同時に認可したい場合は、anyまたはnoneメソッドを使えます:

if (Gate::any(['update-post', 'delete-post'], $post)) {
    // ユーザーは投稿を更新または削除できます...
}

if (Gate::none(['update-post', 'delete-post'], $post)) {
    // ユーザーは投稿を更新も削除もできません...
}

#認可または例外のスロー

アクションの認可を試み、許可されていなければ自動的にIlluminate\Auth\Access\AuthorizationExceptionをスローしたい場合は、Gateファサードのauthorizeメソッドを使います。AuthorizationExceptionはLaravelの例外ハンドラーによって自動的に403 HTTPレスポンスに変換されます:

Gate::authorize('update-post', $post);

// アクションは認可されました...

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

認可用のゲートメソッド(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])) {
    // ユーザーは投稿を作成できます...
}

#ゲートのレスポンス

これまで単純な真偽値を返すゲートを見てきましたが、時にはエラーメッセージを含む詳細なレスポンスを返したい場合があります。その場合は、ゲートから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('管理者である必要があります。');
});

ゲートから認可レスポンスを返しても、Gate::allowsメソッドは単純な真偽値を返しますが、Gate::inspectメソッドを使うとゲートが返した完全な認可レスポンスを取得できます:

$response = Gate::inspect('edit-settings');

if ($response->allowed()) {
    // アクションは認可されました...
} else {
    echo $response->message();
}

Gate::authorizeメソッドを使うと、認可されなかった場合にAuthorizationExceptionをスローしますが、その際に認可レスポンスのエラーメッセージがHTTPレスポンスに反映されます:

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

// アクションは認可されました...

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

ゲートでアクションが拒否されると403 HTTPレスポンスが返されますが、別のHTTPステータスコードを返したい場合もあります。失敗した認可チェックに対して返すHTTPステータスコードは、Illuminate\Auth\Access\ResponseクラスのdenyWithStatus静的コンストラクタでカスタマイズできます:

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

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::allowIfGate::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アプリケーションに含まれる App\Providers\AuthServiceProvider には、Eloquentモデルと対応するポリシーをマッピングする policies プロパティがあります。ポリシーを登録すると、特定のEloquentモデルに対するアクションの認可時にLaravelがどのポリシーを使うかを指示できます。

<?php

namespace App\Providers;

use App\Models\Post;
use App\Policies\PostPolicy;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * アプリケーションのポリシーマッピング。
     *
     * @var array
     */
    protected $policies = [
        Post::class => PostPolicy::class,
    ];

    /**
     * アプリケーションの認証/認可サービスを登録します。
     */
    public function boot(): void
    {
        // ...
    }
}

#ポリシーの自動検出

モデルポリシーを手動で登録する代わりに、モデルとポリシーがLaravelの標準的な命名規則に従っていれば、自動的にポリシーを検出できます。具体的には、ポリシーはモデルを含むディレクトリの上位か同じ階層にある Policies ディレクトリに配置する必要があります。例えば、モデルが app/Models にあり、ポリシーが app/Policies にある場合、Laravelは app/Models/Policiesapp/Policies を順にチェックします。また、ポリシー名はモデル名に Policy を付けた名前である必要があります。例えば、User モデルに対応するポリシーは UserPolicy となります。

独自のポリシー検出ロジックを定義したい場合は、Gate::guessPolicyNamesUsing メソッドを使ってカスタムのポリシー検出コールバックを登録できます。通常、このメソッドはアプリケーションの AuthServiceProviderboot メソッド内で呼び出します。

use Illuminate\Support\Facades\Gate;

Gate::guessPolicyNamesUsing(function (string $modelClass) {
    // 指定されたモデルに対応するポリシークラス名を返す...
});
Внимание

AuthServiceProvider で明示的にマッピングされたポリシーは、自動検出されたポリシーより優先されます。

#ポリシーの作成

#ポリシーメソッド

ポリシークラスを登録したら、認可する各アクションに対応するメソッドを追加できます。例えば、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
{
    /**
     * 指定された投稿をユーザーが更新できるか判定します。
     */
    public function update(User $user, Post $post): bool
    {
        return $user->id === $post->user_id;
    }
}

ポリシーには、認可する各種アクションに応じて必要に応じて追加のメソッドを定義できます。例えば、Postに関連するさまざまなアクションを認可するためにviewdeleteメソッドを定義することが考えられますが、ポリシーのメソッド名は任意に付けて構いません。

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

Примечание

すべてのポリシーはLaravelの サービスコンテナ 経由で解決されるため、ポリシーのコンストラクタで必要な依存を型宣言すれば自動的に注入されます。

#ポリシーレスポンス

これまで単純な真偽値を返すポリシーメソッドを見てきましたが、エラーメッセージなど詳細なレスポンスを返したい場合があります。その場合は、ポリシーメソッドから Illuminate\Auth\Access\Response インスタンスを返せます。

use App\Models\Post;
use App\Models\User;
use Illuminate\Auth\Access\Response;

/**
 * 指定された投稿をユーザーが更新できるか判定します。
 */
public function update(User $user, Post $post): Response
{
    return $user->id === $post->user_id
                ? Response::allow()
                : Response::deny('この投稿の所有者ではありません。');
}

ポリシーから認可レスポンスを返す場合でも、Gate::allows メソッドは単純な真偽値を返しますが、Gate::inspect メソッドを使うとゲートが返す完全な認可レスポンスを取得できます。

use Illuminate\Support\Facades\Gate;

$response = Gate::inspect('update', $post);

if ($response->allowed()) {
    // アクションは認可されました...
} else {
    echo $response->message();
}

Gate::authorize メソッドを使うと、認可されなかった場合に AuthorizationException をスローし、認可レスポンスのエラーメッセージがHTTPレスポンスに反映されます。

Gate::authorize('update', $post);

// アクションは認可されました...

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

ポリシーメソッドでアクションが拒否された場合、通常は 403 HTTPレスポンスが返されますが、別のHTTPステータスコードを返すことも有用です。失敗した認可チェックに対して返すHTTPステータスコードは、Illuminate\Auth\Access\Response クラスの静的コンストラクタ denyWithStatus を使ってカスタマイズできます。

use App\Models\Post;
use App\Models\User;
use Illuminate\Auth\Access\Response;

/**
 * 指定された投稿をユーザーが更新できるか判定します。
 */
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;

/**
 * 指定された投稿をユーザーが更新できるか判定します。
 */
public function update(User $user, Post $post): Response
{
    return $user->id === $post->user_id
                ? Response::allow()
                : Response::denyAsNotFound();
}

#モデルを受け取らないメソッド

一部のポリシーメソッドは、現在認証されているユーザーのインスタンスのみを受け取ります。これは主に create アクションの認可時に多いです。例えばブログを作成する場合、ユーザーが投稿を作成できるかどうかを判定したいことがあります。このような場合、ポリシーメソッドはユーザーインスタンスのみを受け取るべきです。

/**
 * 指定されたユーザーが投稿を作成できるか判定します。
 */
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
{
    /**
     * 指定された投稿をユーザーが更新できるか判定します。
     */
    public function update(?User $user, Post $post): bool
    {
        return $user?->id === $post->user_id;
    }
}

#ポリシーフィルター

特定のユーザーに対して、ポリシー内のすべてのアクションを認可したい場合があります。その場合、ポリシーに before メソッドを定義します。before メソッドは他のメソッドより先に実行され、実際のポリシーメソッドが呼ばれる前に認可を行えます。この機能は主にアプリケーション管理者にすべてのアクションを許可するために使われます。

use App\Models\User;

/**
 * 事前認可チェックを実行します。
 */
public function before(User $user, string $ability): bool|null
{
    if ($user->isAdministrator()) {
        return true;
    }

    return null;
}

特定のユーザータイプに対してすべての認可チェックを拒否したい場合は、before メソッドで false を返せます。null を返すと認可チェックはポリシーメソッドに委ねられます。

Внимание

ポリシークラスに認可対象の能力名と一致するメソッドが存在しない場合、before メソッドは呼ばれません。

#ポリシーを使ったアクションの認可

#Userモデル経由

App\Models\User モデルには、アクションを認可するための便利なメソッド cancannot が用意されています。cancannot メソッドは、認可したいアクション名と該当するモデルを受け取ります。例えば、あるユーザーが特定の 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
{
    /**
     * 指定された投稿を更新します。
     */
    public function update(Request $request, Post $post): RedirectResponse
    {
        if ($request->user()->cannot('update', $post)) {
            abort(403);
        }

        // 投稿を更新する処理...

        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
{
    /**
     * 投稿を作成します。
     */
    public function store(Request $request): RedirectResponse
    {
        if ($request->user()->cannot('create', Post::class)) {
            abort(403);
        }

        // 投稿を作成する処理...

        return redirect('/posts');
    }
}

#コントローラーヘルパー経由

App\Models\User モデルに便利なメソッドがあるほか、Laravelは App\Http\Controllers\Controller を継承したコントローラーに authorize メソッドを提供しています。

can メソッドと同様に、このメソッドは認可したいアクション名と関連するモデルを受け取ります。アクションが認可されていない場合、authorize メソッドは Illuminate\Auth\Access\AuthorizationException 例外をスローし、Laravelの例外ハンドラーが自動的にこれを HTTP 403 ステータスコードのレスポンスに変換します。

<?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
{
    /**
     * 指定されたブログ投稿を更新します。
     *
     * @throws \Illuminate\Auth\Access\AuthorizationException
     */
    public function update(Request $request, Post $post): RedirectResponse
    {
        $this->authorize('update', $post);

        // 現在のユーザーはブログ投稿を更新できます...

        return redirect('/posts');
    }
}

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

前述の通り、create のような一部のポリシーメソッドはモデルインスタンスを必要としません。この場合、authorize メソッドにクラス名を渡すべきです。クラス名は認可時に使用するポリシーを決定するために使われます。

use App\Models\Post;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;

/**
 * 新しいブログ投稿を作成します。
 *
 * @throws \Illuminate\Auth\Access\AuthorizationException
 */
public function create(Request $request): RedirectResponse
{
    $this->authorize('create', Post::class);

    // 現在のユーザーはブログ投稿を作成できます...

    return redirect('/posts');
}

#リソースコントローラーの認可

リソースコントローラーを利用している場合、コントローラーのコンストラクタで authorizeResource メソッドを使えます。このメソッドはリソースコントローラーのメソッドに適切な can ミドルウェア定義を自動で割り当てます。

authorizeResource メソッドは最初の引数にモデルのクラス名を、2番目の引数にモデルIDを含むルート/リクエストパラメータ名を受け取ります。必要なメソッドシグネチャと型ヒントを持つように、リソースコントローラー--model フラグを使って作成してください。

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Models\Post;

class PostController extends Controller
{
    /**
     * コントローラーのインスタンスを作成します。
     */
    public function __construct()
    {
        $this->authorizeResource(Post::class, 'post');
    }
}

以下のコントローラーメソッドは対応するポリシーメソッドにマッピングされます。リクエストが該当のコントローラーメソッドにルーティングされると、コントローラーメソッド実行前に対応するポリシーメソッドが自動的に呼び出されます。

コントローラーメソッド ポリシーメソッド
index viewAny
show view
create create
store create
edit update
update update
destroy delete
Примечание

make:policy コマンドに --model オプションを付けると、指定したモデル用のポリシークラスを素早く生成できます:php artisan make:policy PostPolicy --model=Post

#ミドルウェア経由

Laravel には、リクエストがルートやコントローラーに到達する前にアクションを認可できるミドルウェアが含まれています。デフォルトで Illuminate\Auth\Middleware\Authorize ミドルウェアは App\Http\Kernel クラスの can キーに割り当てられています。can ミドルウェアを使ってユーザーが投稿を更新できるか認可する例を見てみましょう。

use App\Models\Post;

Route::put('/post/{post}', function (Post $post) {
    // 現在のユーザーは投稿を更新できます...
})->middleware('can:update,post');

この例では、can ミドルウェアに2つの引数を渡しています。1つ目は認可したいアクション名、2つ目はポリシーメソッドに渡すルートパラメータです。この場合、暗黙的モデルバインディングを使っているため、App\Models\Post モデルがポリシーメソッドに渡されます。ユーザーがアクションを実行できない場合、ミドルウェアは HTTP 403 ステータスコードのレスポンスを返します。

利便性のため、can ミドルウェアはルートに対して can メソッドを使っても割り当てられます。

use App\Models\Post;

Route::put('/post/{post}', function (Post $post) {
    // 現在のユーザーは投稿を更新できます...
})->can('update', 'post');

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

再度、create のような一部のポリシーメソッドはモデルインスタンスを必要としません。この場合、ミドルウェアにクラス名を渡せます。クラス名は認可時に使用するポリシーを決定するために使われます。

Route::post('/post', function () {
    // 現在のユーザーは投稿を作成できます...
})->middleware('can:create,App\Models\Post');

文字列のミドルウェア定義内に完全なクラス名を指定するのは面倒になることがあります。そのため、can ミドルウェアはルートに対して can メソッドを使って割り当てることもできます。

use App\Models\Post;

Route::post('/post', function () {
    // 現在のユーザーは投稿を作成できます...
})->can('create', Post::class);

#Blade テンプレート経由

Blade テンプレートを書く際、ユーザーが特定のアクションを実行できる場合のみページの一部を表示したいことがあります。例えば、ユーザーが実際に投稿を更新できる場合のみ更新フォームを表示したい場合です。このような場合、@can@cannot ディレクティブを使えます。

@can('update', $post)
    <!-- 現在のユーザーは投稿を更新できます... -->
@elsecan('create', App\Models\Post::class)
    <!-- 現在のユーザーは新しい投稿を作成できます... -->
@else
    <!-- ... -->
@endcan

@cannot('update', $post)
    <!-- 現在のユーザーは投稿を更新できません... -->
@elsecannot('create', App\Models\Post::class)
    <!-- 現在のユーザーは新しい投稿を作成できません... -->
@endcannot

これらのディレクティブは @if@unless 文を書くための便利なショートカットです。上記の @can@cannot は以下の文と同等です。

@if (Auth::user()->can('update', $post))
    <!-- 現在のユーザーは投稿を更新できます... -->
@endif

@unless (Auth::user()->can('update', $post))
    <!-- 現在のユーザーは投稿を更新できません... -->
@endunless

また、ユーザーが複数のアクションのいずれかを実行できるかどうかを判定することもできます。その場合は @canany ディレクティブを使います。

@canany(['update', 'view', 'delete'], $post)
    <!-- 現在のユーザーは投稿を更新、表示、または削除できます... -->
@elsecanany(['create'], \App\Models\Post::class)
    <!-- 現在のユーザーは投稿を作成できます... -->
@endcanany

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

他の多くの認可メソッドと同様に、アクションがモデルインスタンスを必要としない場合は、@can@cannot ディレクティブにクラス名を渡せます。

@can('create', App\Models\Post::class)
    <!-- 現在のユーザーは投稿を作成できます... -->
@endcan

@cannot('create', App\Models\Post::class)
    <!-- 現在のユーザーは投稿を作成できません... -->
@endcannot

#追加のコンテキストを渡す

ポリシーを使ってアクションを認可する際、さまざまな認可関数やヘルパーの第2引数に配列を渡せます。配列の最初の要素は呼び出すポリシーを決定するために使われ、残りの要素はポリシーメソッドのパラメータとして渡され、認可判断の追加コンテキストとして利用できます。例えば、以下の PostPolicy メソッド定義は追加の $category パラメータを含みます。

/**
 * 指定された投稿をユーザーが更新できるか判定します。
 */
public function update(User $user, Post $post, int $category): bool
{
    return $user->id === $post->user_id &&
           $user->canUpdateCategory($category);
}

認証済みユーザーが指定された投稿を更新できるか判定する際、次のようにこのポリシーメソッドを呼び出せます。

/**
 * 指定されたブログ投稿を更新します。
 *
 * @throws \Illuminate\Auth\Access\AuthorizationException
 */
public function update(Request $request, Post $post): RedirectResponse
{
    $this->authorize('update', [$post, $request->category]);

    // 現在のユーザーはブログ投稿を更新できます...

    return redirect('/posts');
}