![見出し画像](https://assets.st-note.com/production/uploads/images/147142092/rectangle_large_type_2_0e48fe38acf65e1635af97079ddc91d0.png?width=1200)
【Laravel】Gateとルーティングに関して、学びのアウトプット
こんにちは!7月も早くも中盤になって、三連休初日ですね。
最近、LaravelのGate関連とルーティング周りのタスクを担当し、
初めてやったタスクなのでブログにしようと思いました。
内容としてシステムの申請処理をPostでした際にGateを使ってチェックするというものです。
今回はアプリケーションの一部をLaravelで実装するケースで作成してみようと思います。
📚 目次
1. 🚪 Gateって何?基本を押さえよう
Gateは、簡単に言えば「誰が何をできるか」を定義する機能です。例えば:
管理者だけが記事を削除できる
投稿者は自分の記事のみ編集できる
プレミアムユーザーだけが特定の機能にアクセスできる
このようなルールを簡単に設定できるんです!
Gateの設定方法
`App\Providers\AuthServiceProvider.php` を開きます。
`boot` メソッド内でGateを定義します。
use Illuminate\Support\Facades\Gate;
public function boot()
{
$this->registerPolicies();
Gate::define('manage-articles', function ($user) {
return $user->role === 'admin';
});
Gate::define('edit-article', function ($user, $article) {
return $user->id === $article->user_id || $user->role === 'admin';
});
}
これで、「manage-articles」と「edit-article」という2つの権限が定義されました。
2. 🛣️ ルーティングの基本おさらい
ルーティングは、URLと処理(コントローラーのアクション)を紐付ける機能です。簡単に言えば、「どのURLにアクセスしたらどの処理を行うか」を決めるものです。
基本的なルーティング
`routes/web.php` でルートを定義します:
use App\Http\Controllers\ArticleController;
Route::get('/articles', [ArticleController::class, 'index']);
Route::get('/articles/{id}', [ArticleController::class, 'show']);
Route::post('/articles', [ArticleController::class, 'store']);
Route::put('/articles/{id}', [ArticleController::class, 'update']);
Route::delete('/articles/{id}', [ArticleController::class, 'destroy']);
これで、記事の一覧表示、詳細表示、作成、更新、削除の基本的なルートが設定されました。
3. 🔀 GateとルーティングのSタンパイ品の組み合わせ
さて、ここからが本題です。GateとルーティングSタンパイ品はどのように組み合わせて使うのでしょうか?
ミドルウェアを使用する方法
ルートにGateチェックを適用する最も簡単な方法は、`can` ミドルウェアを使うことです:
Route::put('/articles/{id}', [ArticleController::class, 'update'])
->middleware('can:edit-article,article');
Route::delete('/articles/{id}', [ArticleController::class, 'destroy'])
->middleware('can:manage-articles');
これで、記事の更新は記事の所有者か管理者のみが、削除は管理者のみが行えるようになりました。
4. 🚀 実践!ブログシステムを作ってみよう
では、実際のブログシステムを例に、GateとルーティングSタンパイ品の使い方を見てみましょう。
ステップ1:Gateの定義
public function boot()
{
$this->registerPolicies();
Gate::define('create-article', function ($user) {
return $user->is_writer || $user->is_admin;
});
Gate::define('edit-article', function ($user, $article) {
return $user->id === $article->user_id || $user->is_admin;
});
Gate::define('delete-article', function ($user) {
return $user->is_admin;
});
Gate::define('submit-article', function ($user, $article) {
return $user->id === $article->user_id && $article->status === 'draft';
});
Gate::define('cancel-article', function ($user, $article) {
return $user->id === $article->user_id && $article->status === 'pending';
});
}
ステップ2:ルーティングの設定
Route::post('/articles', [ArticleController::class, 'store'])
->middleware('can:create-article');
Route::put('/articles/{id}', [ArticleController::class, 'update'])
->middleware('can:edit-article,article');
Route::delete('/articles/{id}', [ArticleController::class, 'destroy'])
->middleware('can:delete-article');
Route::post('/articles/{id}/submit', [ArticleController::class, 'submit'])
->middleware('can:submit-article,article');
Route::post('/articles/{id}/cancel', [ArticleController::class, 'cancel'])
->middleware('can:cancel-article,article');
ステップ3:コントローラーの実装
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class ArticleController extends Controller
{
public function submit($id)
{
return $this->updateArticleStatus($id, 'pending', 'submit-article');
}
public function cancel($id)
{
return $this->updateArticleStatus($id, 'draft', 'cancel-article');
}
private function updateArticleStatus($id, $newStatus, $ability)
{
try {
return DB::transaction(function () use ($id, $newStatus, $ability) {
$article = Article::findOrFail($id);
if (Gate::denies($ability, $article)) {
abort(403, '権限がありません。');
}
$article->status = $newStatus;
$article->save();
return redirect()->route('articles.show', $article->id)
->with('success', '記事のステータスが更新されました。');
});
} catch (\Exception $e) {
Log::error('記事ステータス更新エラー: ' . $e->getMessage());
return back()->withErrors('記事の更新中にエラーが発生しました。');
}
}
}
5. 🛡️ エラーハンドリングで完璧を目指す
最後に、エラーハンドリングを実装して、アプリケーションをさらに堅牢にしましょう。
app/Exceptions/Handler.php の修正
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Database\Eloquent\ModelNotFoundException;
class Handler extends ExceptionHandler
{
public function render($request, Throwable $exception)
{
if ($exception instanceof AuthorizationException) {
return response()->view('errors.403', [], 403);
}
if ($exception instanceof ModelNotFoundException) {
return response()->view('errors.404', [], 404);
}
return parent::render($request, $exception);
}
}
これで、権限エラーや「Not Found」エラーが発生した場合、ユーザーフレンドリーなエラーページが表示されるようになりました。
🎉 まとめ
今回は、LaravelのGateとルーティングを使って、セキュアなWebアプリケーションを構築する方法を紹介しました。
Gateで詳細な権限設定ができる
ルーティングとGateを組み合わせて、URLレベルでのアクセス制御が可能
トランザクション処理でデータの整合性を保証
エラーハンドリングでユーザーエクスペリエンスを向上
これらの技術を使いこなすことで、より安全で使いやすいWebアプリケーションが作れると思ってます。
今週もお疲れ様でした。! 🚀✨
この記事が参加している募集
この記事が気に入ったらサポートをしてみませんか?