Readouble

Laravel 10.x 認可

イントロダクションIntroduction

組み込み認証サービスの提供に加え、Laravelは特定のリソースに対するユーザーアクションを認可する手軽な方法も提供しています。たとえば、あるユーザーが認証されていても、アプリケーションが管理している特定のEloquentモデルまたはデータベースレコードを更新や削除する権限を持っていない場合があるでしょう。Laravelの認可機能は、こうしたタイプの認可チェックを管理するための簡単で組織化された方法を提供します。In addition to providing built-in authentication[/docs/{{version}}/authentication] services, Laravel also provides a simple way to authorize user actions against a given resource. For example, even though a user is authenticated, they may not be authorized to update or delete certain Eloquent models or database records managed by your application. Laravel's authorization features provide an easy, organized way of managing these types of authorization checks.

Laravelは、アクションを認可する2つの主要な方法を提供します。ゲートポリシーです。ゲートとポリシーは、ルートやコントローラのようなものだと考えてください。ゲートは認可のためのクロージャベースのシンプルなアプローチを提供します。一方でポリシーはコントローラのように、特定のモデルやリソース周辺のロジックをひとかたまりにまとめます。このドキュメントでは、最初にゲートを説明し、その後でポリシーを見ていきましょう。Laravel provides two primary ways of authorizing actions: gates[#gates] and policies[#creating-policies]. Think of gates and policies like routes and controllers. Gates provide a simple, closure-based approach to authorization while policies, like controllers, group logic around a particular model or resource. In this documentation, we'll explore gates first and then examine policies.

アプリケーションを構築するときに、ゲートのみを使用するか、ポリシーのみを使用するかを選択する必要はありません。ほとんどのアプリケーションには、ゲートとポリシーが混在する可能性が高く、それはまったく問題ありません。ゲートは、管理者ダッシュボードの表示など、モデルやリソースに関連しないアクションに最も適しています。対照的に、特定のモデルまたはリソースのアクションを認可する場合は、ポリシーを使用する必要があります。You do not need to choose between exclusively using gates or exclusively using policies when building an application. Most applications will most likely contain some mixture of gates and policies, and that is perfectly fine! Gates are most applicable to actions that are not related to any model or resource, such as viewing an administrator dashboard. In contrast, policies should be used when you wish to authorize an action for a particular model or resource.

ゲートGates

ゲートの作成Writing Gates

warning Warning! ゲートは、Laravelの認可機能の基本を学ぶための優れた方法です。ただし、堅牢なLaravelアプリケーションを構築するときは、ポリシーを使用して認可ルールを整理することを検討する必要があります。[!WARNING]
Gates are a great way to learn the basics of Laravel's authorization features; however, when building robust Laravel applications you should consider using policies[#creating-policies] to organize your authorization rules.

ゲートは、ユーザーが特定のアクションを実行することを許可されているかどうかを判断する単なるクロージャです。通常、ゲートは、Gateファサードを使用してApp\Providers\AuthServiceProviderクラスのbootメソッド内で定義されます。ゲートは常に最初の引数としてユーザーインスタンスを受け取り、オプションで関連するEloquentモデルなどの追加の引数を受け取る場合があります。Gates are simply closures that determine if a user is authorized to perform a given action. Typically, gates are defined within the boot method of the App\Providers\AuthServiceProvider class using the Gate facade. Gates always receive a user instance as their first argument and may optionally receive additional arguments such as a relevant Eloquent model.

以下の例では、ユーザーが特定のApp\Models\Postモデルを更新できるかどうかを判断するためのゲートを定義します。ユーザーのidと、投稿を作成したユーザーのuser_idを比較することで、このゲートは可否を判定します。In this example, we'll define a gate to determine if a user can update a given App\Models\Post model. The gate will accomplish this by comparing the user's id against the user_id of the user that created the post:

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

コントローラと同様に、ゲートもクラスコールバック配列を使用して定義できます。Like controllers, gates may also be defined using a class callback array:

use App\Policies\PostPolicy;
use Illuminate\Support\Facades\Gate;

/**
 * 全認証/認可サービスの登録
 */
public function boot(): void
{
    Gate::define('update-post', [PostPolicy::class, 'update']);
}

アクションの認可Authorizing Actions

ゲートを使用してアクションを認可するには、Gateファサードが提供するallowsdeniesメソッドを使用する必要があります。現在認証済みのユーザーをこれらのメソッドに渡す必要はないことに注意してください。Laravelは自動的にユーザーをゲートクロージャに引き渡します。認可が必要なアクションを実行する前に、アプリケーションのコントローラ内でゲート認可メソッドを呼び出すのが一般的です。To authorize an action using gates, you should use the allows or denies methods provided by the Gate facade. Note that you are not required to pass the currently authenticated user to these methods. Laravel will automatically take care of passing the user into the gate closure. It is typical to call the gate authorization methods within your application's controllers before performing an action that requires authorization:

<?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 you would like to determine if a user other than the currently authenticated user is authorized to perform an action, you may use the forUser method on the Gate facade:

if (Gate::forUser($user)->allows('update-post', $post)) {
    // ユーザーは投稿を更新可能
}

if (Gate::forUser($user)->denies('update-post', $post)) {
    // ユーザーは投稿を更新不可能
}

anyまたはnoneメソッドを使用して、一度に複数のアクション認可を確認できます。You may authorize multiple actions at a time using the any or none methods:

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

if (Gate::none(['update-post', 'delete-post'], $post)) {
    // ユーザーは投稿を更新または削除不可能
}

認可または例外を投げるAuthorizing or Throwing Exceptions

アクションを認可をチェックし、ユーザーが指定のアクションの実行を許可されていない場合は、Illuminate\Auth\Access\AuthorizationExceptionを自動で投げたい場合は、Gateファサードのauthorizeメソッドを使用します。AuthorizationExceptionのインスタンスは、Laravelの例外ハンドラによって自動的に403HTTPレスポンスへ変換されます。If you would like to attempt to authorize an action and automatically throw an Illuminate\Auth\Access\AuthorizationException if the user is not allowed to perform the given action, you may use the Gate facade's authorize method. Instances of AuthorizationException are automatically converted to a 403 HTTP response by Laravel's exception handler:

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

// アクションは認可されている

追加コンテキストの提供Supplying Additional Context

アビリティを認可するためのゲートメソッド(allowsdenischeckanynoneauthorizecancannot)と認可Bladeディレクティブ@can@cannot@canany)は、2番目の引数として配列を取れます。これらの配列要素は、パラメータとしてゲートクロージャに渡され、認可を決定する際の追加のコンテキストに使用できます。The gate methods for authorizing abilities (allows, denies, check, any, none, authorize, can, cannot) and the authorization Blade directives[#via-blade-templates] (@can, @cannot, @canany) can receive an array as their second argument. These array elements are passed as parameters to the gate closure, and can be used for additional context when making authorization decisions:

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])) {
    // ユーザーは投稿を作成可能
}

ゲートのレスポンスGate Responses

これまで、単純な論理値を返すゲートのみ見てきました。しかし、エラーメッセージなどのより詳細なレスポンスを返したい場合もあります。これには、ゲートからIlluminate\Auth\Access\Responseを返してください。So far, we have only examined gates that return simple boolean values. However, sometimes you may wish to return a more detailed response, including an error message. To do so, you may return an Illuminate\Auth\Access\Response from your gate:

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メソッドを使用して、ゲートから返される完全な認可レスポンスを取得できます。Even when you return an authorization response from your gate, the Gate::allows method will still return a simple boolean value; however, you may use the Gate::inspect method to get the full authorization response returned by the gate:

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

if ($response->allowed()) {
    // アクションは認可されている
} else {
    echo $response->message();
}

アクションが認可されていない場合にAuthorizationExceptionを投げるGate::authorizeメソッドを使用すると、認可レスポンスが提供するエラーメッセージがHTTPレスポンスへ伝播されます。When using the Gate::authorize method, which throws an AuthorizationException if the action is not authorized, the error message provided by the authorization response will be propagated to the HTTP response:

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

// アクションは認可されている

HTTPレスポンスステータスのカスタマイズCustomizing The HTTP Response Status

ゲートがアクションを拒否すると、403 HTTPレスポンスを返します。しかし場合により、別のHTTPステータスコードを返すほうが、便利なことがあります。認可チェックに失敗したときに返すHTTPステータスコードは、Illuminate\Auth\Access\ResponseクラスのdenyWithStatus静的コンストラクタを使用してカスタマイズできます。When an action is denied via a Gate, a 403 HTTP response is returned; however, it can sometimes be useful to return an alternative HTTP status code. You may customize the HTTP status code returned for a failed authorization check using the denyWithStatus static constructor on the Illuminate\Auth\Access\Response class:

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メソッドを提供しています。Because hiding resources via a 404 response is such a common pattern for web applications, the denyAsNotFound method is offered for convenience:

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

ゲートチェックの割り込みIntercepting Gate Checks

特定のユーザーにすべての機能を付与したい場合があります。beforeメソッドを使用して、他のすべての認可チェックの前に実行するクロージャを定義できます。Sometimes, you may wish to grant all abilities to a specific user. You may use the before method to define a closure that is run before all other authorization checks:

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

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

beforeクロージャがnull以外の結果を返した場合、その結果を許可チェックの結果とみなします。If the before closure returns a non-null result that result will be considered the result of the authorization check.

afterメソッドを使用して、他のすべての認可チェックの後に実行されるクロージャを定義できます。You may use the after method to define a closure to be executed after all other authorization checks:

use App\Models\User;

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

beforeメソッドと同様に、afterクロージャがnull以外の結果を返した場合、その結果は認可チェックの結果とみなします。Similar to the before method, if the after closure returns a non-null result that result will be considered the result of the authorization check.

インライン認可Inline Authorization

時には、現在認証されているユーザーが、あるアクションを実行する認可を持っているかを、そのアクションに対応する専用のゲートを書かずに判断したいこともあるでしょう。Laravelでは、Gate::allowIfGate::denyIfメソッドを使い、「インライン」での認可チェックを行うことができます。インライン認可は、定義した"before"と"after"の認可フックを実行しません。Occasionally, you may wish to determine if the currently authenticated user is authorized to perform a given action without writing a dedicated gate that corresponds to the action. Laravel allows you to perform these types of "inline" authorization checks via the Gate::allowIf and Gate::denyIf methods. Inline authorization does not execute any defined "before" or "after" authorization hooks[#intercepting-gate-checks]:

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レスポンスへ変換します。If the action is not authorized or if no user is currently authenticated, Laravel will automatically throw an Illuminate\Auth\Access\AuthorizationException exception. Instances of AuthorizationException are automatically converted to a 403 HTTP response by Laravel's exception handler.

ポリシーの作成Creating Policies

ポリシーの生成Generating Policies

ポリシーは、特定のモデルまたはリソースに関する認可ロジックを集めたクラスです。たとえば、アプリケーションがブログの場合、App\Models\Postモデルと投稿の作成や更新などのユーザーアクションを認可するためのPostモデルと対応するApp\Policies\PostPolicyがあるでしょう。Policies are classes that organize authorization logic around a particular model or resource. For example, if your application is a blog, you may have an App\Models\Post model and a corresponding App\Policies\PostPolicy to authorize user actions such as creating or updating posts.

make:policy Artisanコマンドを使用してポリシーを生成できます。生成するポリシーはapp/Policiesディレクトリへ配置します。このディレクトリがアプリケーションに存在しない場合、Laravelが作成します。You may generate a policy using the make:policy Artisan command. The generated policy will be placed in the app/Policies directory. If this directory does not exist in your application, Laravel will create it for you:

php artisan make:policy PostPolicy

make:policyコマンドは、空のポリシークラスを生成します。リソースの表示、作成、更新、削除に関連するポリシーメソッドのサンプルを含んだクラスを生成する場合は、コマンドの実行時に--modelオプションを指定します。The make:policy command will generate an empty policy class. If you would like to generate a class with example policy methods related to viewing, creating, updating, and deleting the resource, you may provide a --model option when executing the command:

php artisan make:policy PostPolicy --model=Post

ポリシーの登録Registering Policies

ポリシークラスを作成したら、登録する必要があります。ポリシーの登録とは、特定のモデルタイプに対するアクションを認可するときに、使用するポリシーをLaravelに指示する方法です。Once the policy class has been created, it needs to be registered. Registering policies is how we can inform Laravel which policy to use when authorizing actions against a given model type.

新しいLaravelアプリケーションに含まれているApp\Providers\AuthServiceProviderには、Eloquentモデルを対応するポリシーにマップするpoliciesプロパティが含まれています。ポリシーを登録すると、特定のEloquentモデルに対するアクションを認可するときに使用するポリシーがLaravelに指示されます。The App\Providers\AuthServiceProvider included with fresh Laravel applications contains a policies property which maps your Eloquent models to their corresponding policies. Registering a policy will instruct Laravel which policy to utilize when authorizing actions against a given Eloquent model:

<?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
    {
        // ...
    }
}

ポリシーの自動検出Policy Auto-Discovery

モデルポリシーを手作業で登録する代わりに、モデルとポリシーが標準のLaravel命名規約に従っている限り、Laravelはポリシーを自動的に検出できます。具体的にポリシーは、モデルを含むディレクトリが存在する階層より上のPoliciesディレクトリにある必要があります。したがって、たとえばモデルはapp/Modelsディレクトリに配置し、ポリシーはapp/Policiesディレクトリに配置する場合があるでしょう。この場合、Laravelはapp/Models/Policies、次にapp/Policiesのポリシーをチェックします。さらに、ポリシー名はモデル名と一致し、Policyサフィックスが付いている必要があります。したがって、UserモデルはUserPolicyポリシークラスに対応します。Instead of manually registering model policies, Laravel can automatically discover policies as long as the model and policy follow standard Laravel naming conventions. Specifically, the policies must be in a Policies directory at or above the directory that contains your models. So, for example, the models may be placed in the app/Models directory while the policies may be placed in the app/Policies directory. In this situation, Laravel will check for policies in app/Models/Policies then app/Policies. In addition, the policy name must match the model name and have a Policy suffix. So, a User model would correspond to a UserPolicy policy class.

独自のポリシー検出ロジックを定義する場合は、Gate::guessPolicyNamesUsingメソッドを使用してカスタムポリシー検出コールバックを登録できます。通常、このメソッドは、アプリケーションのAuthServiceProviderbootメソッドから呼び出す必要があります。If you would like to define your own policy discovery logic, you may register a custom policy discovery callback using the Gate::guessPolicyNamesUsing method. Typically, this method should be called from the boot method of your application's AuthServiceProvider:

use Illuminate\Support\Facades\Gate;

Gate::guessPolicyNamesUsing(function (string $modelClass) {
    // 指定されたモデルに対するポリシークラスの名前を返す…
});

warning Warning! AuthServiceProviderで明示的にマッピングされるポリシーは、自動検出される可能性のあるポリシーよりも優先されます。[!WARNING]
Any policies that are explicitly mapped in your AuthServiceProvider will take precedence over any potentially auto-discovered policies.

ポリシーの作成Writing Policies

ポリシーメソッドPolicy Methods

ポリシークラスを登録したら、認可するアクションごとにメソッドを追加できます。例として、あるApp\Models\UserがあるApp\Models\Postインスタンスを更新できるかどうかを決定するPostPolicyupdateメソッドを定義してみましょう。Once the policy class has been registered, you may add methods for each action it authorizes. For example, let's define an update method on our PostPolicy which determines if a given App\Models\User can update a given App\Models\Post instance.

updateメソッドは引数としてUserPostインスタンスを受け取り、そのユーザーが指定したPostを更新する権限があるかどうかを示すtrueまたはfalseを返す必要があります。したがって、この例では、ユーザーのidが投稿のuser_idと一致することを確認しています。The update method will receive a User and a Post instance as its arguments, and should return true or false indicating whether the user is authorized to update the given Post. So, in this example, we will verify that the user's id matches the user_id on the post:

<?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メソッドを定義して、さまざまなPost関連のアクションを認可できますが、ポリシーメソッドには任意の名前を付けることができることを覚えておいてください。You may continue to define additional methods on the policy as needed for the various actions it authorizes. For example, you might define view or delete methods to authorize various Post related actions, but remember you are free to give your policy methods any name you like.

Artisanコンソールを介してポリシーを生成するときに--modelオプションを使用した場合、はじめからviewAnyviewcreateupdatedeleterestoreforceDeleteアクションのメソッドが用意されます。If you used the --model option when generating your policy via the Artisan console, it will already contain methods for the viewAny, view, create, update, delete, restore, and forceDelete actions.

lightbulb Note: すべてのポリシーはLaravelサービスコンテナを介して解決されるため、ポリシーのコンストラクターで必要な依存関係をタイプヒントして、自動的に依存注入することができます。[!NOTE]
All policies are resolved via the Laravel service container[/docs/{{version}}/container], allowing you to type-hint any needed dependencies in the policy's constructor to have them automatically injected.

ポリシーのレスポンスPolicy Responses

これまで、単純な論理値値を返すポリシーメソッドについてのみ説明してきました。しかし、エラーメッセージなどより詳細なレスポンスを返したい場合があります。これにはポリシーメソッドからIlluminate\Auth\Access\Responseインスタンスを返してください。So far, we have only examined policy methods that return simple boolean values. However, sometimes you may wish to return a more detailed response, including an error message. To do so, you may return an Illuminate\Auth\Access\Response instance from your policy method:

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メソッドは単純な論理値を返します。ただし、Gate::inspectメソッドを使用して、ゲートが返す完全な認可レスポンスを取得できます。When returning an authorization response from your policy, the Gate::allows method will still return a simple boolean value; however, you may use the Gate::inspect method to get the full authorization response returned by the gate:

use Illuminate\Support\Facades\Gate;

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

if ($response->allowed()) {
    // アクションは認可されている
} else {
    echo $response->message();
}

アクションが認可されていない場合にAuthorizationExceptionを投げるGate::authorizeメソッドを使用すると、認可レスポンスが提供するエラーメッセージがHTTPレスポンスへ伝播されます。When using the Gate::authorize method, which throws an AuthorizationException if the action is not authorized, the error message provided by the authorization response will be propagated to the HTTP response:

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

// アクションは認可されている

HTTPレスポンスステータスのカスタマイズCustomizing the HTTP Response Status

ポリシーメソッドがアクションを拒否すると、403 HTTPレスポンスを返します。しかし場合により、別のHTTPステータスコードを返すほうが、便利なことがあります。認可チェックに失敗したときに返すHTTPステータスコードは、Illuminate\Auth\Access\ResponseクラスのdenyWithStatus静的コンストラクタを使用してカスタマイズできます。When an action is denied via a policy method, a 403 HTTP response is returned; however, it can sometimes be useful to return an alternative HTTP status code. You may customize the HTTP status code returned for a failed authorization check using the denyWithStatus static constructor on the Illuminate\Auth\Access\Response class:

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メソッドを提供しています。Because hiding resources via a 404 response is such a common pattern for web applications, the denyAsNotFound method is offered for convenience:

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

モデルのないメソッドMethods Without Models

一部のポリシーメソッドは、現在認証済みユーザーのインスタンスのみを受け取ります。この状況は、createアクションを認可するばあいに頻繁に見かけます。たとえば、ブログを作成している場合、ユーザーが投稿の作成を認可されているかを確認したい場合があります。このような状況では、ポリシーメソッドはユーザーインスタンスのみを受け取る必要があります。Some policy methods only receive an instance of the currently authenticated user. This situation is most common when authorizing create actions. For example, if you are creating a blog, you may wish to determine if a user is authorized to create any posts at all. In these situations, your policy method should only expect to receive a user instance:

/**
 * 指定ユーザーが投稿を作成可能か確認
 */
public function create(User $user): bool
{
    return $user->role == 'writer';
}

ゲストユーザーGuest Users

デフォルトでは、受信HTTPリクエストが認証済みユーザーによって開始されたものでない場合、すべてのゲートとポリシーは自動的にfalseを返します。ただし、「オプションの」タイプヒントを宣言するか、ユーザーの引数定義でnullのデフォルト値を指定することで、これらの認可チェックをゲートとポリシーに渡すことができます。By default, all gates and policies automatically return false if the incoming HTTP request was not initiated by an authenticated user. However, you may allow these authorization checks to pass through to your gates and policies by declaring an "optional" type-hint or supplying a null default value for the user argument definition:

<?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」メソッドを定義します。beforeメソッドは、ポリシー上の他のメソッドの前に実行されるため、目的のポリシーメソッドが実際に呼び出される前にアクションを認可する機会に利用できます。この機能は、アプリケーション管理者にアクションの実行を許可するために最も一般的に使用されます。For certain users, you may wish to authorize all actions within a given policy. To accomplish this, define a before method on the policy. The before method will be executed before any other methods on the policy, giving you an opportunity to authorize the action before the intended policy method is actually called. This feature is most commonly used for authorizing application administrators to perform any action:

use App\Models\User;

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

    return null;
}

特定のタイプのユーザー全員の認可チェックを拒否したい場合は、beforeメソッドからfalseを返してください。nullを返す場合は、認可チェックはポリシーメソッドへ委ねられます。If you would like to deny all authorization checks for a particular type of user then you may return false from the before method. If null is returned, the authorization check will fall through to the policy method.

warning Warning! ポリシークラスのbeforeメソッドは、チェックしている機能の名前と一致する名前のメソッドがクラスに含まれていない場合は呼び出されません。[!WARNING]
The before method of a policy class will not be called if the class doesn't contain a method with a name matching the name of the ability being checked.

ポリシーを使用したアクションの認可Authorizing Actions Using Policies

ユーザーモデル経由Via the User Model

Laravelアプリケーションに含まれているApp\Models\Userモデルには、アクションを認可するための2つの便利なメソッドcancannotが含まれています。canメソッドとcannotメソッドは、認可するアクションの名前と関連するモデルを受け取ります。たとえば、ユーザーが特定のApp\Models\Postモデルを更新する権限を持っているかどうかを確認しましょう。通常、これはコントローラメソッド内で実行されます。The App\Models\User model that is included with your Laravel application includes two helpful methods for authorizing actions: can and cannot. The can and cannot methods receive the name of the action you wish to authorize and the relevant model. For example, let's determine if a user is authorized to update a given App\Models\Post model. Typically, this will be done within a controller method:

<?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メソッドは、指定されたアクション名に一致するクロージャベースのゲートを呼び出そうとします。If a policy is registered[#registering-policies] for the given model, the can method will automatically call the appropriate policy and return the boolean result. If no policy is registered for the model, the can method will attempt to call the closure-based Gate matching the given action name.

モデルを必要としないアクションActions That Don't Require Models

一部のアクションは、モデルインスタンスを必要としないcreateなどのポリシーメソッドに対応する場合があることに注意してください。このような状況では、クラス名をcanメソッドに渡すことができます。クラス名は、アクションを認可するときに使用するポリシーを決定するために使用されます。Remember, some actions may correspond to policy methods like create that do not require a model instance. In these situations, you may pass a class name to the can method. The class name will be used to determine which policy to use when authorizing the action:

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

コントローラヘルパ経由Via Controller Helpers

Laravelは、App\Models\Userモデルが提供する便利なメソッドに加えて、App\Http\Controllers\Controller基本クラスを拡張する任意のコントローラに役立つauthorizeメソッドを提供します。In addition to helpful methods provided to the App\Models\User model, Laravel provides a helpful authorize method to any of your controllers which extend the App\Http\Controllers\Controller base class.

canメソッドと同様に、このメソッドは、認可するアクションの名前とリレーションモデルを受け入れます。アクションが認可されていない場合、authorizeメソッドはIlluminate\Auth\Access\AuthorizationException例外を投げ、Laravel例外ハンドラは自動的に403ステータスコードのHTTPレスポンスに変換します。Like the can method, this method accepts the name of the action you wish to authorize and the relevant model. If the action is not authorized, the authorize method will throw an Illuminate\Auth\Access\AuthorizationException exception which the Laravel exception handler will automatically convert to an HTTP response with a 403 status code:

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

モデルを必要としないアクションActions That Don't Require Models

すでに説明したように、createなどの一部のポリシーメソッドはモデルインスタンスを必要としません。このような状況では、クラス名をauthorizeメソッドに渡す必要があります。クラス名は、アクションを認可するときに使用するポリシーを決定するために使用されます。As previously discussed, some policy methods like create do not require a model instance. In these situations, you should pass a class name to the authorize method. The class name will be used to determine which policy to use when authorizing the action:

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

リソースコントローラの認可Authorizing Resource Controllers

リソースコントローラを使用している場合は、コントローラのコンストラクターでauthorizeResourceメソッドを使用できます。このメソッドは、適切なcanミドルウェア定義をリソースコントローラのメソッドにアタッチします。If you are utilizing resource controllers[/docs/{{version}}/controllers#resource-controllers], you may make use of the authorizeResource method in your controller's constructor. This method will attach the appropriate can middleware definitions to the resource controller's methods.

authorizeResourceメソッドは、最初の引数としてモデルのクラス名を受け入れ、2番目の引数としてモデルのIDを含むルート/リクエストパラメーターの名前を受け入れます。リソースコントローラ--modelフラグを使用して作成されていることを確認して、必要なメソッド引数とタイプヒントが含まれるようにしてください。The authorizeResource method accepts the model's class name as its first argument, and the name of the route / request parameter that will contain the model's ID as its second argument. You should ensure your resource controller[/docs/{{version}}/controllers#resource-controllers] is created using the --model flag so that it has the required method signatures and type hints:

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

以下のコントローラメソッドは、対応するポリシーメソッドにマップされています。リクエストが特定のコントローラメソッドにルーティングされると、コントローラメソッドが実行される前に、対応するポリシーメソッドが自動的に呼び出されます。The following controller methods will be mapped to their corresponding policy method. When requests are routed to the given controller method, the corresponding policy method will automatically be invoked before the controller method is executed:

コントローラメソッドController Method ポリシーメソッドPolicy Method
indexindex viewAnyviewAny
showshow viewview
createcreate createcreate
storestore createcreate
editedit updateupdate
updateupdate updateupdate
destroydestroy deletedelete

lightbulb Note: make:policyコマンドを--modelオプションとともに使用し、特定のモデルのポリシークラスを手早く生成できます。php artisan make:policy PostPolicy --model=Post[!NOTE]
You may use the make:policy command with the --model option to quickly generate a policy class for a given model: php artisan make:policy PostPolicy --model=Post.

ミドルウェア経由Via Middleware

Laravelには、受信リクエストがルートやコントローラに到達する前にアクションを認可できるミドルウェアが含まれています。デフォルトでは、Illuminate\Auth\Middleware\AuthorizeミドルウェアにはApp\Http\Kernelクラスのcanキーが割り当てられています。canミドルウェアを使用して、ユーザーが投稿を更新できることを認可する例を見てみましょう。Laravel includes a middleware that can authorize actions before the incoming request even reaches your routes or controllers. By default, the Illuminate\Auth\Middleware\Authorize middleware is assigned the can key in your App\Http\Kernel class. Let's explore an example of using the can middleware to authorize that a user can update a post:

use App\Models\Post;

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

この例では、canミドルウェアに2つの引数を渡します。1つ目は認可するアクションの名前であり、2つ目はポリシーメソッドに渡すルートパラメーターです。この場合、暗黙のモデルバインディングを使用しているため、App\Models\Postモデルがポリシーメソッドに渡されます。ユーザーが特定のアクションを実行する権限を持っていない場合、ミドルウェアは403ステータスコードのHTTPレスポンスを返します。In this example, we're passing the can middleware two arguments. The first is the name of the action we wish to authorize and the second is the route parameter we wish to pass to the policy method. In this case, since we are using implicit model binding[/docs/{{version}}/routing#implicit-binding], an App\Models\Post model will be passed to the policy method. If the user is not authorized to perform the given action, an HTTP response with a 403 status code will be returned by the middleware.

これは簡単に、canメソッドを使い、canミドルウェアをルートへ指定できます。For convenience, you may also attach the can middleware to your route using the can method:

use App\Models\Post;

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

モデルを必要としないアクションActions That Don't Require Models

繰り返しますが、createのようないくつかのポリシーメソッドはモデルインスタンスを必要としません。このような状況では、クラス名をミドルウェアに渡すことができます。クラス名は、アクションを認可するときに使用するポリシーを決定するために使用されます。Again, some policy methods like create do not require a model instance. In these situations, you may pass a class name to the middleware. The class name will be used to determine which policy to use when authorizing the action:

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

ミドルウェア定義の中で、クラス名全体を文字列で指定するのは面倒です。そのため、canメソッドを使って、canミドルウェアをルートへ指定できます。Specifying the entire class name within a string middleware definition can become cumbersome. For that reason, you may choose to attach the can middleware to your route using the can method:

use App\Models\Post;

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

Bladeテンプレート経由Via Blade Templates

Bladeテンプレートを作成するとき、ユーザーが特定のアクションを実行する許可がある場合にのみ、ページの一部を表示したい場合があります。たとえば、ユーザーが実際に投稿を更新できる場合にのみ、ブログ投稿の更新フォームを表示したい場合があります。この状況では、@canおよび@cannotディレクティブを使用できます。When writing Blade templates, you may wish to display a portion of the page only if the user is authorized to perform a given action. For example, you may wish to show an update form for a blog post only if the user can actually update the post. In this situation, you may use the @can and @cannot directives:

@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ステートメントは、以下のステートメントと同等です。These directives are convenient shortcuts for writing @if and @unless statements. The @can and @cannot statements above are equivalent to the following statements:

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

@unless (Auth::user()->can('update', $post))
    <!-- 現在のユーザーは投稿を更新不可能 -->
@endunless

また、ユーザーが複数のアクションの実行を認可されているかを判定することもできます。これには、@cananyディレクティブを使用します。You may also determine if a user is authorized to perform any action from a given array of actions. To accomplish this, use the @canany directive:

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

モデルを必要としないアクションActions That Don't Require Models

他のほとんどの認可メソッドと同様に、アクションがモデルインスタンスを必要としない場合は、クラス名を@canおよび@cannotディレクティブに渡すことができます。Like most of the other authorization methods, you may pass a class name to the @can and @cannot directives if the action does not require a model instance:

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

@cannot('create', App\Models\Post::class)
    <!-- 現在のユーザーは投稿を作成不可能 -->
@endcannot

追加コンテキストの提供Supplying Additional Context

ポリシーを使用してアクションを認可する場合、2番目の引数としてさまざまな認可関数とヘルパに配列を渡すことができます。配列の最初の要素は、呼び出すポリシーを決定するために使用され、残りの配列要素は、パラメーターとしてポリシーメソッドに渡され、認可の決定を行う際の追加のコンテキストに使用できます。たとえば、追加の$categoryパラメータを含む次のPostPolicyメソッド定義について考えてみます。When authorizing actions using policies, you may pass an array as the second argument to the various authorization functions and helpers. The first element in the array will be used to determine which policy should be invoked, while the rest of the array elements are passed as parameters to the policy method and can be used for additional context when making authorization decisions. For example, consider the following PostPolicy method definition which contains an additional $category parameter:

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

認証済みユーザーが特定の投稿を更新できるか判断する場合、次のようにこのポリシーメソッドを呼び出すことができます。When attempting to determine if the authenticated user can update a given post, we can invoke this policy method like so:

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

    // 現在のユーザーはブログ投稿を更新可能

    return redirect('/posts');
}

章選択

設定

明暗テーマ
light_mode
dark_mode
brightness_auto システム設定に合わせる
テーマ選択
photo_size_select_actual デフォルト
photo_size_select_actual モノクローム(白黒)
photo_size_select_actual Solarized風
photo_size_select_actual GitHub風(青ベース)
photo_size_select_actual Viva(黄緑ベース)
photo_size_select_actual Happy(紫ベース)
photo_size_select_actual Mint(緑ベース)
コードハイライトテーマ選択

明暗テーマごとに、コードハイライトのテーマを指定できます。

テーマ配色確認
スクリーン表示幅
640px
80%
90%
100%

768px以上の幅があるときのドキュメント部分表示幅です。

インデント
無し
1rem
2rem
3rem
原文確認
原文を全行表示
原文を一行ずつ表示
使用しない

※ 段落末のEボタンへカーソルオンで原文をPopupします。

Diff表示形式
色分けのみで区別
行頭の±で区別
削除線と追記で区別

※ [tl!…]形式の挿入削除行の表示形式です。

テストコード表示
両コード表示
Pestのみ表示
PHPUnitのみ表示
OS表示
全OS表示
macOSのみ表示
windowsのみ表示
linuxのみ表示
和文変換

対象文字列と置換文字列を半角スペースで区切ってください。(最大5組各10文字まで)

本文フォント

総称名以外はCSSと同様に、"〜"でエスケープしてください。

コードフォント

総称名以外はCSSと同様に、"〜"でエスケープしてください。

保存内容リセット

localStrageに保存してある設定項目をすべて削除し、デフォルト状態へ戻します。

ヘッダー項目移動

キーボード操作