本文へ移動
Laravel Tips

できることを決める(認可)

ログインした人に「何をしてよいか」を決める認可を、ゲートとポリシーの作り方、使い方、Blade やミドルウェアからの確かめ方まで説明します。

Laravel には、ログインの確認(認証)のほかに、認可の機能があります。認可とは、「この人は、この操作をしてよいか」を決めることです。たとえば、ログインしていても、ほかの人の記事を編集や削除してよいとは限りません。認可の機能を使うと、こうした確認を、整理して簡単に書けます。

認可を書く方法は、ゲートとポリシーの2つです。ゲートは、ルートのように、クロージャ(名前のない関数)で簡単に書く方法です。ポリシーは、コントローラーのように、特定のモデル(データベースの表を扱うクラス)や、特定の対象にまつわる確認を、1つのクラスにまとめる方法です。

どちらか一方だけを使う必要はありません。たいていのアプリは両方を使います。ゲートは、管理画面を見るなど、モデルや対象に関係のない操作に向いています。ポリシーは、特定のモデルや対象に対する操作に使います。

ゲート(Gates)#

ゲートを書く#

注意

ゲートは、認可の基本を学ぶのにはよい方法です。ただ、しっかりしたアプリを作るなら、認可のルールの整理には、あとで説明するポリシーを考えてください。

ゲートは、「ユーザーがその操作をしてよいか」を決める、ただのクロージャです。ふつう、App\Providers\AppServiceProvider の boot(アプリの起動のときに呼ばれるメソッド)の中で、Gate ファサード(Gate::define() のように、クラス名と :: で機能を呼べる窓口)を使って定義します。ゲートの第1引数には、いつもユーザーが渡されます。第2引数からは、関係する Eloquent のモデルなどを、必要に応じて受け取れます。

次の例は、ユーザーが App\Models\Post(記事)を更新してよいかを決めるゲートです。ユーザーの id と、記事を作ったユーザーの user_id が同じかを調べます。

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

コントローラーのように、クラスとメソッド名の配列でも定義できます。

php
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
<?php

namespace App\Http\Controllers;

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 を使います。

php
if (Gate::forUser($user)->allows('update-post', $post)) {
    // そのユーザーは、記事を更新できる
}

if (Gate::forUser($user)->denies('update-post', $post)) {
    // そのユーザーは、記事を更新できない
}

複数の操作をまとめて確かめるには、any か none を使います。

php
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 レスポンス(「禁止」を表すエラー)に変えてくれます。

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

// 操作は許されている

追加の情報を渡す#

操作を確かめるゲートのメソッドと、認可の Blade ディレクティブ(@ で始まる Blade の命令)は、第2引数に配列を受け取れます。メソッドは allows・denies・check・any・none・authorize・can・cannot、ディレクティブは @can・@cannot・@canany です。配列の要素は、ゲートのクロージャの引数として渡され、判断の材料に使えます。

php
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])) {
    // そのユーザーは、記事を作れる
}

ゲートのレスポンス#

ここまでのゲートは、true か false を返すだけでした。エラーメッセージを含む、もっとくわしい答えを返したいときは、ゲートから Illuminate\Auth\Access\Response を返します。

php
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 は、true か false だけを返します。くわしいレスポンスを受け取るには、Gate::inspect を使います。

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

if ($response->allowed()) {
    // 操作は許されている
} else {
    echo $response->message();
}

許されないときに例外を投げる Gate::authorize を使うと、レスポンスのエラーメッセージが、HTTP レスポンスにそのまま伝わります。

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

// 操作は許されている

HTTP のステータスを変える#

ゲートで操作が断られると、403 の HTTP レスポンスが返ります。別のステータスコード(結果を表す3けたの番号)にしたいときは、Illuminate\Auth\Access\Response の denyWithStatus を使います。

php
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 という近道があります。

php
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 で、ほかの確認よりも先に動くクロージャを定義できます。

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

Gate::before(function (User $user, string $ability) {
    if ($user->isAdministrator()) {
        return true;
    }
});

before のクロージャが null ではない値を返すと、その値が確認の結果になります。

after で、ほかの確認のあとに動くクロージャも定義できます。

php
use App\Models\User;

Gate::after(function (User $user, string $ability, bool|null $result, mixed $arguments) {
    if ($user->isAdministrator()) {
        return true;
    }
});

after のクロージャが返した値は、ゲートやポリシーが null を返したときを除き、確認の結果を上書きしません。

その場で確かめる(Inline Authorization)#

その操作のためのゲートを作らずに、ログイン中のユーザーがその操作をしてよいかを、その場で確かめたいことがあります。Gate::allowIf と Gate::denyIf を使います。この方法では、定義済みの「before」「after」は動きません。

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

Gate::allowIf(fn (User $user) => $user->isAdministrator());

Gate::denyIf(fn (User $user) => $user->banned());

操作が許されないとき、またはログイン中のユーザーがいないときは、Illuminate\Auth\Access\AuthorizationException が自動で投げられます。この例外は、Laravel の例外ハンドラ(例外の処理を担当するしくみ)が、403 の HTTP レスポンスに変えます。

ポリシーを作る#

ポリシーを生成する#

ポリシーは、特定のモデルや対象にまつわる認可の考え方を、まとめたクラスです。たとえば、ブログなら、App\Models\Post のモデルに、記事の作成や更新を確かめる App\Policies\PostPolicy を対応させます。

make:policy という Artisan コマンド(php artisan で動かす Laravel のコマンド)で、ポリシーを作ります。app/Policies に置かれます。そのフォルダがなければ、Laravel が作ります。

bash
php artisan make:policy PostPolicy

make:policy は、空のポリシーのクラスを作ります。リソースの表示・作成・更新・削除のための例のメソッドがほしいときは、--model オプションを付けます。

bash
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 の中で呼びます。

php
use Illuminate\Support\Facades\Gate;

Gate::guessPolicyNamesUsing(function (string $modelClass) {
    // そのモデルのポリシーのクラス名を返す...
});

ポリシーを手動で登録する#

Gate ファサードで、ポリシーと対応するモデルを、手動で登録できます。アプリの AppServiceProvider の boot の中で呼びます。

php
use App\Models\Order;
use App\Policies\OrderPolicy;
use Illuminate\Support\Facades\Gate;

/**
 * アプリのサービスを起動する
 */
public function boot(): void
{
    Gate::policy(Order::class, OrderPolicy::class);
}

モデルのクラスに UsePolicy 属性(PHP の、クラスの前に書く印)を付けて、そのモデルのポリシーを Laravel に知らせることもできます。

php
<?php

namespace App\Models;

use App\Policies\OrderPolicy;
use Illuminate\Database\Eloquent\Attributes\UsePolicy;
use Illuminate\Database\Eloquent\Model;

#[UsePolicy(OrderPolicy::class)]
class Order extends Model
{
    //
}

ポリシーを書く#

ポリシーのメソッド#

ポリシーを登録したら、確かめたい操作ごとに、メソッドを足します。たとえば、PostPolicy に、App\Models\User が App\Models\Post を更新してよいかを決める update メソッドを作ります。

update は、User と Post を受け取り、ユーザーがその Post を更新してよいかを、true か false で返します。ここでは、ユーザーの id が、記事の user_id と同じかを調べます。

php
<?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;
    }
}

確かめたい操作に合わせて、ほかのメソッドも足せます。たとえば、view や delete です。ポリシーのメソッドの名前は、自由に付けられます。

ポリシーを作るときに --model オプションを使うと、次の操作のメソッドが、最初から入っています。

メソッド 説明
viewAny 表示(一覧)の操作のためのメソッド
view 表示の操作のためのメソッド
create 作成の操作のためのメソッド
update 更新の操作のためのメソッド
delete 削除の操作のためのメソッド
restore 復元の操作のためのメソッド
forceDelete 完全な削除の操作のためのメソッド

補足

ポリシーは、どれも Laravel のサービスコンテナ(クラスを作って渡してくれる道具箱のようなしくみ)が作ります。そのため、ポリシーのコンストラクタ(クラスを作るときに最初に動くメソッド)に、必要なクラスの型を書いておけば、自動で渡されます。

ポリシーのレスポンス#

ここまでのポリシーのメソッドは、true か false を返すだけでした。エラーメッセージを含む、もっとくわしい答えを返したいときは、Illuminate\Auth\Access\Response を返します。

php
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('You do not own this post.');
}

ポリシーがこのレスポンスを返しても、Gate::allows は、true か false だけを返します。くわしいレスポンスを受け取るには、Gate::inspect を使います。

php
use Illuminate\Support\Facades\Gate;

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

if ($response->allowed()) {
    // 操作は許されている
} else {
    echo $response->message();
}

Gate::authorize を使うと、許されないときに例外を投げ、レスポンスのエラーメッセージが、HTTP レスポンスに伝わります。

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

// 操作は許されている

HTTP のステータスを変える#

ポリシーのメソッドで操作が断られると、403 の HTTP レスポンスが返ります。別のステータスにしたいときは、Illuminate\Auth\Access\Response の denyWithStatus を使います。

php
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 です。

php
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(作成)の操作を確かめるときに多いです。たとえば、ブログで、ユーザーが記事を作ってよいかだけを知りたい場合は、ユーザーだけを受け取ります。

php
/**
 * ユーザーが、記事を作ってよいか決める
 */
public function create(User $user): bool
{
    return $user->role == 'writer';
}

ゲストのユーザー#

ログインしていないユーザーのリクエストは、ふつう、すべてのゲートとポリシーが、自動で false を返します。ゲスト(ログインしていない人)でも、ゲートやポリシーまで通したいときは、ユーザーの引数の型を「省略できる」にするか、null を既定値にします。

php
<?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;
    }
}

ポリシーの前処理(Policy Filters)#

特定のユーザーには、ポリシーのすべての操作を許したいことがあります。ポリシーに before メソッドを定義します。ポリシーのほかのメソッドよりも先に動くので、本来のメソッドが呼ばれる前に、許可を出せます。アプリの管理者に、すべての操作を許すときによく使います。

php
use App\Models\User;

/**
 * 事前の認可の確認をする
 */
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 です。確かめたい操作の名前と、関係するモデルを渡します。たとえば、ユーザーが App\Models\Post を更新してよいかを確かめます。ふつう、コントローラーのメソッドの中で使います。

php
<?php

namespace App\Http\Controllers;

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 は、合うポリシーを自動で呼び、true か false を返します。ポリシーが登録されていなければ、can は、その操作の名前に合う、クロージャのゲートを呼ぼうとします。

モデルが要らない操作#

create のように、モデルのインスタンス(1件ぶんの実物のデータ)が要らない操作もあります。そのときは、can にクラスの名前を渡します。クラスの名前から、使うポリシーが決まります。

php
<?php

namespace App\Http\Controllers;

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

Gate ファサードから確かめる#

ユーザーのモデルのメソッドのほかに、Gate ファサードの authorize でも、いつでも確かめられます。

can と同じように、確かめたい操作の名前と、関係するモデルを渡します。操作が許されないと、Illuminate\Auth\Access\AuthorizationException が投げられ、Laravel の例外ハンドラが、403 の HTTP レスポンスに変えます。

php
<?php

namespace App\Http\Controllers;

use App\Models\Post;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;

class PostController extends Controller
{
    /**
     * ブログの記事を更新する
     *
     * @throws \Illuminate\Auth\Access\AuthorizationException
     */
    public function update(Request $request, Post $post): RedirectResponse
    {
        Gate::authorize('update', $post);

        // いまのユーザーは、記事を更新できる...

        return redirect('/posts');
    }
}

モデルが要らない操作#

create のように、モデルのインスタンスが要らないときは、authorize にクラスの名前を渡します。

php
use App\Models\Post;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;

/**
 * 新しいブログの記事を作る
 *
 * @throws \Illuminate\Auth\Access\AuthorizationException
 */
public function create(Request $request): RedirectResponse
{
    Gate::authorize('create', Post::class);

    // いまのユーザーは、記事を作れる...

    return redirect('/posts');
}

ミドルウェアから確かめる#

Laravel には、リクエストが、ルートやコントローラーに届く前に、操作を確かめるミドルウェア(リクエストが処理に届く前に、間に入って確かめる処理)があります。Illuminate\Auth\Middleware\Authorize を、can というミドルウェアの別名(短い呼び名。Laravel が自動で登録)で、ルートに付けられます。ユーザーが記事を更新してよいかを確かめる例です。

php
use App\Models\Post;

Route::put('/post/{post}', function (Post $post) {
    // いまのユーザーは、記事を更新してよい
})->middleware('can:update,post');

この例では、can ミドルウェアに、2つの引数を渡しています。1つ目は、確かめたい操作の名前、2つ目は、ポリシーのメソッドへ渡すルートのパラメータ(URL の {post} の部分)です。ここでは、暗黙のモデルバインディング(URL の値から、自動でモデルを取り出すしくみ。ルーティングを見てください)が使われるので、App\Models\Post のモデルが、ポリシーのメソッドへ渡されます。操作が許されなければ、ミドルウェアが 403 の HTTP レスポンスを返します。

ルートの can メソッドでも、同じように付けられます。

php
use App\Models\Post;

Route::put('/post/{post}', function (Post $post) {
    // いまのユーザーは、記事を更新してよい
})->can('update', 'post');

コントローラーのミドルウェアの属性を使っているなら、Authorize 属性で付けられます。

php
use Illuminate\Routing\Attributes\Controllers\Authorize;

#[Authorize('update', 'post')]
public function update(Post $post)
{
    // いまのユーザーは、記事を更新してよい
}

モデルが要らない操作#

create のように、モデルのインスタンスが要らない操作では、ミドルウェアにクラスの名前を渡します。

php
Route::post('/post', function () {
    // いまのユーザーは、記事を作ってよい
})->middleware('can:create,App\Models\Post');

文字でクラスの名前を全部書くのは、面倒です。そのときは、ルートの can メソッドを使います。

php
use App\Models\Post;

Route::post('/post', function () {
    // いまのユーザーは、記事を作ってよい
})->can('create', Post::class);

Blade のテンプレートから確かめる#

Blade のテンプレート(画面の見た目を書いたファイル)では、ユーザーがその操作を許されているときだけ、画面の一部を出したいことがあります。たとえば、ユーザーが記事を更新できるときだけ、更新のフォームを出します。そのときは、@can と @cannot のディレクティブを使います。

blade
@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 は、次の書き方と同じです。

blade
@if (Auth::user()->can('update', $post))
    <!-- いまのユーザーは、記事を更新できる -->
@endif

@unless (Auth::user()->can('update', $post))
    <!-- いまのユーザーは、記事を更新できない -->
@endunless

配列に並べた操作のうち、どれか1つでも許されているかを調べるには、@canany を使います。

blade
@canany(['update', 'view', 'delete'], $post)
    <!-- いまのユーザーは、記事を更新・表示・削除のどれかできる -->
@elsecanany(['create'], \App\Models\Post::class)
    <!-- いまのユーザーは、記事を作れる -->
@endcanany
ディレクティブ 説明
@can その操作が許されているときだけ、中を出す
@elsecan 前の @can が許されなかったときに、別の操作が許されているなら、中を出す
@cannot その操作が許されていないときだけ、中を出す
@elsecannot 前の @cannot に当てはまらなかったときに、別の操作が許されていないなら、中を出す
@canany 配列の操作のうち、どれか1つでも許されているときだけ、中を出す
@elsecanany 前の @canany に当てはまらなかったときに、別の操作のどれかが許されているなら、中を出す

モデルが要らない操作#

ほかの認可のメソッドと同じく、モデルのインスタンスが要らない操作では、@can と @cannot にクラスの名前を渡せます。

blade
@can('create', App\Models\Post::class)
    <!-- いまのユーザーは、記事を作れる -->
@endcan

@cannot('create', App\Models\Post::class)
    <!-- いまのユーザーは、記事を作れない -->
@endcannot

追加の情報を渡す#

ポリシーで操作を確かめるとき、いろいろな認可の関数やヘルパーの第2引数に、配列を渡せます。配列の最初の要素で、どのポリシーを呼ぶかが決まります。残りの要素は、ポリシーのメソッドの引数として渡され、判断の材料になります。たとえば、追加の $category を受け取る PostPolicy のメソッドです。

php
/**
 * ユーザーが、その記事を更新してよいか決める
 */
public function update(User $user, Post $post, int $category): bool
{
    return $user->id === $post->user_id &&
           $user->canUpdateCategory($category);
}

ログイン中のユーザーが、その記事を更新してよいかを確かめるときは、次のように呼べます。

php
/**
 * ブログの記事を更新する
 *
 * @throws \Illuminate\Auth\Access\AuthorizationException
 */
public function update(Request $request, Post $post): RedirectResponse
{
    Gate::authorize('update', [$post, $request->category]);

    // いまのユーザーは、記事を更新できる...

    return redirect('/posts');
}

認可と Inertia#

認可は、必ずサーバー側でします。ただ、画面を正しく出すために、認可の情報を、画面を作る側(フロントエンド)に渡したいこともあります。Inertia(サーバーのコードと画面のコードをつなぐしくみ)で動く画面へ、認可の情報をどう渡すかについて、Laravel は、決まった方法を定めていません。

Laravel の Inertia を使ったスターターキットを使っているなら、アプリには、HandleInertiaRequests ミドルウェアが入っています。その share メソッドで、アプリのすべての Inertia のページに渡す、共有のデータを返せます。この共有のデータは、ユーザーの認可の情報を置く、便利な場所になります。

php
<?php

namespace App\Http\Middleware;

use App\Models\Post;
use Illuminate\Http\Request;
use Inertia\Middleware;

class HandleInertiaRequests extends Middleware
{
    // ...

    /**
     * 既定で共有するプロパティを決める
     *
     * @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),
                    ],
                ],
            ],
        ];
    }
}

関連するページ#

公式ドキュメント(英語)

2026年10月5日時点の内容をもとに、日本語でまとめています。

ページの一覧