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 でユーザ認証とマルチ認証を実現する

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

コメントの編集

次にコメントの編集機能の実装に取り掛かります.今回は自分自身が投稿したコメントの編集(および削除)ができますが,他のユーザが投稿したコメントは閲覧だけが許可され,編集や削除はできないようにします.

まず,コントローラの show 関数ではログイン中のユーザ情報を取得し,その情報をビューに渡します.

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

コメントが自分自身の投稿であるかどうかをビューで判断するには次のようにします.

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)
                            自分自身が投稿したコメントです
                        @else
                            自分のコメントではありません
                        @endif
                    </div>
                </div>
            </div>
        </div>
    </div>
</x-app-layout>

自分で投稿したコメントのページを表示します.

laravel10-2023-auth-83.png

他のユーザが投稿したコメントを表示します.

laravel10-2023-auth-84.png

続いて,ルート情報を記載します.やはりメール検証済みのユーザがログインした状態で更新ページの表示や更新処理を行えるようにします.

routes/web.php(抜粋)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::post('/comments', [CommentController::class, 'store'])->name('comments.store');
    Route::patch('/comments', [CommentController::class, 'update'])->name('comments.update');
});

コントローラに編集フォームを表示するページの関数 edit と,実際に更新処理を行う関数 update を定義します.例によって update 関数はフォームから送信された情報を表示するだけにしておきます.また,edit 関数もデータベースから取得したコメント情報とログイン中のユーザ情報を表示するようにします.

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

        dd($comment, $user);
        // return view('comments.show')
        //         ->with('comment', $comment)
        //         ->with('user', $user);
    }

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

コメント詳細表示のビューに「コメント編集」のリンクを設置します.ただし,このリンクは表示されているコメントがログイン中のユーザが投稿者である場合にのみ表示されるようにしています.

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>
                            </div>
                        @endif
                    </div>
                </div>
            </div>
        </div>
    </div>
</x-app-layout>

自身で投稿したコメントを表示すると「コメントの編集」リンクが表示されたので,このリンクをクリックします.

laravel10-2023-auth-85.png

コメントの情報とユーザの情報を取得できていることがわかります.

laravel10-2023-auth-86.png

コントローラの edit 関数を変更します.ここで,コメントの投稿者とログイン中のユーザが異なればコメント一覧に強制的にリダイレクトしています.詳細ページには投稿者でなければリンクが表示されませんが,/comments/コメントID/edit という URL が分かれば,任意のコメントIDを指定して編集ページを表示できてしまうため,自分のコメントであるかのチェックをこの段階で行っておく必要があります.

app/Http/Controllers/CommentController.php(抜粋)    public function edit($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.edit')
                ->with('comment', $comment)
                ->with('user', $user);
    }

編集のためのビューを新たに作成します.内容には新規投稿と共通する部分が多くあります.しかし,コメントの ID や投稿者の ID もフォームに含めておきます.

resources/views/comments/edit.blade.php<x-app-layout>
    <x-slot name="header">
        <h2 class="font-semibold text-xl text-gray-800 leading-tight">
            {{ __('Edit 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">投稿者:</div>
                        <div class="text-base text-gray-800 indent-4">{{ $user->name }}</div>

                        <form method="POST" action="{{ route('comments.update') }}">
                            @csrf
                            {{ method_field('patch') }}
                            <input type="hidden" name="comment_id" value="{{ $comment->id }}">
                            <input type="hidden" name="user_id" value="{{ $user->id }}">

                            <div class="mt-2">
                                <x-input-label for="title" :value="__('タイトル')" />
                                <x-text-input id="title" class="block mt-1 w-full" type="text" name="title" value="{{ $comment->title }}" placeholder="コメントのタイトルを入力してください" required autofocus />
                                <x-input-error :messages="$errors->get('title')" class="mt-2" />
                            </div>

                            <div class="mt-2">
                                <x-input-label for="body" :value="__('本文')" />
                                <textarea id="body"
                                class="block mt-1 mb-2 w-full border-gray-300 focus:border-indigo-500 focus:ring-indigo-500 rounded-md shadow-sm"
                                type="text" name="body" rows="3" maxlength="250" placeholder="コメントの本文を入力してください">{{ $comment->body }}</textarea>
                                <x-input-error :messages="$errors->get('body')" class="mt-2" />
                            </div>

                            <x-primary-button class="block w-full mt-2">
                                {{ __('コメントの編集') }}
                            </x-primary-button>

                        </form>
                    </div>
                </div>
            </div>
        </div>
    </div>
</x-app-layout>

一旦ここで更新ページを表示します.

laravel10-2023-auth-87.png

タイトルや本文を変更して「コメントの編集」ボタンを押下します.

laravel10-2023-auth-88.png

フォームから送信された情報を確認します.この中に,コメントの ID だけでなく,投稿者の ID (user_id) も含まれていることに注意してください.

laravel10-2023-auth-89.png

コントローラに実際に投稿を更新する機能を実装します.この中でフォームに含められた user_id とログイン中ユーザの ID が一致するかどうかを確認していることに注意して下さい.さらに取得したコメントの投稿者とログイン中のユーザを比較する機能も加えるとより安全性が高まります.あるいは,7行目でコメントを取得するときの条件にコメントの所有者とログインユーザが一致するというものを追加しても良いでしょう.

app/Http/Controllers/CommentController.php(抜粋)    public function update(Request $request)
    {
        $this->validate($request, [
            'title' => 'required|max:10',
            'body'  => 'required|max:250'
        ]);
        $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->title = $request->title;
        $comment->body = $request->body;
        $comment->save();
        return redirect('/comments');
    }

ここまででコメントの編集機能が実装できました.実際に修正した結果を示します.

laravel10-2023-auth-90.png

目次に戻る