Laravel 10 入門トップページ


目次

  1. 全体の概要
  2. Laravel によるユーザ認証
  3. ユーザ認証を備えたコメント掲示板の開発
    1. 概要
    2. データベースのマイグレーション
    3. シーダによるコメントデータの登録
    4. モデルとコントローラの生成
    5. ルートの定義と確認
    6. 未検証ユーザの動作検証
    7. コメントの一覧表示
    8. ナビゲーションメニューの追加
    9. コメント一覧の Tailwind CSS によるスタイリング
    10. コメントの詳細ページ
    11. リレーションシップの設定と投稿者名の表示
    12. ページネーションの作成
    13. コメントの投稿
    14. コメントの編集
    15. コメントの削除
    16. ナビゲーションのハイライトを調整
  4. マルチ認証の実現

Laravel でユーザ認証とマルチ認証を実現する

ユーザ認証を備えたコメント掲示板の開発

コメントの削除

コメントを削除する場合も投稿者でなければ許可されないようにします.また,削除ボタンを押してそのまま削除されるのではなく,一旦確認画面を表示して,さらにボタンを押してはじめて削除されるようにします.

まずルート情報を定義します.

routes/web.php
<?php

use App\Http\Controllers\ProfileController;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\CommentController;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider and all of them will
| be assigned to the "web" middleware group. Make something great!
|
*/

Route::get('/', function () {
    return view('welcome');
});

Route::get('/dashboard', function () {
    return view('dashboard');
})->middleware(['auth', 'verified'])->name('dashboard');

Route::middleware('auth')->group(function () {
    Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit');
    Route::patch('/profile', [ProfileController::class, 'update'])->name('profile.update');
    Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');
});

// 'verified' を 'auth' と一緒に利用することでメール認証後にしかログインできなくなる
Route::middleware('auth', 'verified')->group(function () {
    Route::get('/comments', [CommentController::class, 'index'])->name('comments.index');
    Route::get('/comments/create', [CommentController::class, 'create'])->name('comments.create');
    Route::get('/comments/{comment_id}', [CommentController::class, 'show'])->name('comments.show');
    Route::get('/comments/{comment_id}/edit', [CommentController::class, 'edit'])->name('comments.edit');
    Route::get('/comments/{comment_id}/delete', [CommentController::class, 'delete'])->name('comments.delete');
    Route::post('/comments', [CommentController::class, 'store'])->name('comments.store');
    Route::patch('/comments', [CommentController::class, 'update'])->name('comments.update');
    Route::delete('/comments', [CommentController::class, 'destroy'])->name('comments.destroy');
});

require __DIR__.'/auth.php';

詳細表示のビューに削除のためのリンクを設置します.ただし編集の時と同様に削除のリンクも投稿者のみに表示するようにします.

resources/views/comments/show.blade.php
<x-app-layout>
    <x-slot name="header">
        <h2 class="font-semibold text-xl text-gray-800 leading-tight">
            {{ __('Comment') }}
        </h2>
    </x-slot>

    <div class="py-12">
        <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
            <div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
                <div class="p-6 text-gray-900">
                    <div class="my-2 border border-gray-300 rounded-md p-3">
                        <div class="text-sm text-gray-700">Owner:</div>
                        <div class="text-base text-gray-800 indent-4">{{ $comment->user->name }}</div>
                        <div class="text-sm text-gray-700">Title:</div>
                        <div class="text-lg font-semibold text-gray-800 indent-4">{{ $comment->title }}</div>
                        <div class="text-sm text-gray-700">Body:</div>
                        <div class="text-base text-gray-800 indent-4">{{ $comment->body }}</div>
                        <div class="text-xs text-gray-600 pt-4">Created_at: {{ $comment->created_at }} / Updated_at: {{ $comment->updated_at }}</div>
                        @if ($comment->user_id == $user->id)
                            <hr class="my-2">
                            <div class="text-sm">
                                <a href="{{ route('comments.edit', $comment->id) }}" class="text-blue-500 hover:text-blue-800 hover:underline active:text-blue-900 active:bg-gray-200 transition ease-in-out duration-150">
                                    コメントの編集
                                </a>
                                <a href="{{ route('comments.delete', $comment->id) }}" class="text-blue-500 hover:text-blue-800 hover:underline active:text-blue-900 active:bg-gray-200 transition ease-in-out duration-150 ml-5">
                                    コメントの削除
                                </a>
                            </div>
                        @endif
                    </div>
                </div>
            </div>
        </div>
    </div>
</x-app-layout>

コントローラに deletedestroy 関数を定義します.ここで delete 関数はその大半が edit 関数と同じです.

app/Http/Controllers/CommentController.php(抜粋)
    public function delete($comment_id)
    {
        $comment = Comment::where('id', '=', $comment_id)
                ->first();
        if (!$comment) {
            return redirect('/comments');
        }
        $user = Auth::user();
        if ($comment->user_id != $user->id) {
            return redirect('/comments');
        }
        return view('comments.delete')
                ->with('comment', $comment)
                ->with('user', $user);
    }

    public function destroy(Request $request)
    {
        dd($request);
    }

削除の確認ページを作成します.

resources/views/comments/delete.blade.php
<x-app-layout>
    <x-slot name="header">
        <h2 class="font-semibold text-xl text-gray-800 leading-tight">
            {{ __('Delete Comment') }}
        </h2>
    </x-slot>

    <div class="py-12">
        <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
            <div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
                <div class="p-6 text-gray-900">
                    <div class="my-2 border border-gray-300 rounded-md p-3">
                        <div class="text-sm text-gray-700">Owner:</div>
                        <div class="text-base text-gray-800 indent-4">{{ $comment->user->name }}</div>
                        <div class="text-sm text-gray-700">Title:</div>
                        <div class="text-base text-gray-800 indent-4">{{ $comment->title }}</div>
                        <div class="text-sm text-gray-700">Body:</div>
                        <div class="text-base text-gray-800 indent-4">{{ $comment->body }}</div>
                        <div class="text-xs text-gray-600 pt-4">Created_at: {{ $comment->created_at }} / Updated_at: {{ $comment->updated_at }}</div>

                        <hr class="mt-3 mb-3">

                        <div class="text-xl font-bold text-red-800">本当に削除しますか?</div>
                        <form method="POST" action="{{ route('comments.destroy') }}">
                            @csrf
                            {{ method_field('delete') }}
                            <input type="hidden" name="comment_id" value="{{ $comment->id }}">
                            <input type="hidden" name="user_id" value="{{ $user->id }}">

                            <x-primary-button class="block mt-2 bg-red-600 hover:bg-red-200 focus:bg-red-200 active:bg-red-400">
                                {{ __('コメントの削除') }}
                            </x-primary-button>
                        </form>
                    </div>
                </div>
            </div>
        </div>
    </div>
</x-app-layout>

削除したいコメントを表示して「コメントの削除」リンクをクリックします.

laravel10-2023-auth-91.png

そのまま削除されるわけではなく,一旦確認のページが表示されます.

laravel10-2023-auth-92.png

ボタンにマウスがポイントされた状態のデザインがスタイリングされています.

laravel10-2023-auth-93.png

ボタンを押している最中の状態のデザインもスタイリングされています.

laravel10-2023-auth-94.png

削除ボタンを押した時にフォームから送信された内容が確認できます.

laravel10-2023-auth-95.png

この確認ができれば実際に destroy 関数にコメントを削除する機能を実装します.

app/Http/Controllers/CommentController.php(抜粋)
    public function destroy(Request $request)
    {
        $comment = Comment::where('id', '=', $request->comment_id)
                ->first();
        if (!$comment) {
            return redirect('/comments');
        }
        $user = Auth::user();
        if ($request->user_id != $user->id) {
            return redirect('/comments');
        }
        $comment->delete();
        return redirect('/comments');
    }

先頭に表示されていたコメントが削除されました.

laravel10-2023-auth-96.png

目次に戻る