#16 Laravel基礎
ゲートとポリシーで認可を実装する
認証と認可の違い
- 認証(Authentication):あなたは誰か?(ログイン)
- 認可(Authorization):あなたにそれをする権限はあるか?
Laravelの ゲート? 「この操作をしてよいか」という認可ルールを定義する仕組み。`Gate::allows()`でシンプルに確認できる。 と ポリシー? モデルに紐づいた認可ロジックをまとめるクラス。「このユーザーはこの投稿を編集できるか」などのルールをまとめて管理できる。 は「認可」を管理するための仕組みです。
ゲート(Gate)
ゲート? 「この操作をしてよいか」という認可ルールを定義する仕組み。`Gate::allows()`でシンプルに確認できる。 はシンプルなクロージャーで認可ロジックを定義します。特定のモデルに紐づかないルールに向いています。
ゲートを定義する
// 📁 app/Providers/AppServiceProvider.php
use Illuminate\Support\Facades\Gate;
public function boot(): void
{
// 管理者かどうかチェックするゲート
Gate::define('admin-only', function ($user) {
return $user->role === 'admin';
});
// 投稿を更新できるかチェックするゲート
Gate::define('update-post', function ($user, $post) {
return $user->id === $post->user_id;
});
}
ゲートを使う
コントローラーで:
// 📁 app/Http/Controllers/PostController.php
use Illuminate\Support\Facades\Gate;
public function update(Request $request, Post $post)
{
// 権限がなければ403エラー
Gate::authorize('update-post', $post);
$post->update($request->only('title', 'body'));
return redirect()->route('posts.show', $post);
}
ビューで:
@can('update-post', $post)
<a href="{{ route('posts.edit', $post) }}">編集</a>
@endcan
ポリシー(Policy)
ポリシー? モデルに紐づいた認可ロジックをまとめるクラス。「このユーザーはこの投稿を編集できるか」などのルールをまとめて管理できる。 は特定のモデルに関する認可ロジックをクラスにまとめます。CRUD操作の認可が複数ある場合に整理しやすくなります。
ポリシーを生成する
php artisan make:policy PostPolicy --model=Post
<?php
// 📁 app/Policies/PostPolicy.php
namespace App\Policies;
use App\Models\Post;
use App\Models\User;
class PostPolicy
{
// 一覧を見られるか(全員OK)
public function viewAny(User $user): bool
{
return true;
}
// 詳細を見られるか
public function view(User $user, Post $post): bool
{
return true;
}
// 作成できるか
public function create(User $user): bool
{
return true;
}
// 更新できるか(自分の投稿だけ)
public function update(User $user, Post $post): bool
{
return $user->id === $post->user_id;
}
// 削除できるか(自分の投稿、または管理者)
public function delete(User $user, Post $post): bool
{
return $user->id === $post->user_id || $user->role === 'admin';
}
}
ポリシーを登録する
モデルと同名のポリシーを app/Policies/ に置けば自動で認識されます(Laravel 9以降)。
コントローラーでポリシーを使う
authorize() メソッドはポリシーも自動で参照します。
// 📁 app/Http/Controllers/PostController.php
public function update(Request $request, Post $post)
{
// PostPolicy の update() を自動で呼ぶ
$this->authorize('update', $post);
$post->update($request->only('title', 'body'));
return redirect()->route('posts.show', $post);
}
public function destroy(Post $post)
{
$this->authorize('delete', $post);
$post->delete();
return redirect()->route('posts.index');
}
ビューでポリシーを使う
@can('update', $post)
<a href="{{ route('posts.edit', $post) }}">編集</a>
@endcan
@can('delete', $post)
<form method="POST" action="{{ route('posts.destroy', $post) }}">
@csrf
@method('DELETE')
<button type="submit">削除</button>
</form>
@endcan
ポリシーでモデルを使わないアクション
create のように特定のインスタンスが存在しない場合は、モデルの第2引数を省略します。
// コントローラー
$this->authorize('create', Post::class);
// ビュー
@can('create', App\Models\Post::class)
<a href="{{ route('posts.create') }}">新規作成</a>
@endcan
まとめ
- ゲートは
AppServiceProviderにクロージャーで定義する(シンプルなルール向け) - ポリシーはモデルに紐づく認可ロジックをクラスにまとめる(CRUD向け)
- コントローラーでは
$this->authorize()で認可チェックできる - ビューでは
@can/@cannotディレクティブを使う
次回はファイルのアップロードとストレージ管理を学びます。