E090 管理画面 ユーザー管理機能の導入

今回は登録されたユーザーを管理する機能を実装する方法を紹介します。

ユーザー管理機能作成

①ユーザー管理用のコントローラーを作成する。

Userモデルは既に存在するので、モデル生成は行なわずコントローラーのみを作成します。通常はRequestクラスも合わせて作成しますが、ユーザー管理ではRequestクラスを使わない形での実装を行ないます。

$sail artisan make:controller Admin/UserController --resource --model=User

②ルーティングを追加する。

予約管理機能用のルーティングを追加します。

※下記、L43を参照

routes/admin.php
  Route::middleware('auth:admin')->group(function () {
      //中略
  
+   Route::resource('user', UserController::class);
  });

③Controllerの参照を追加する。

他管理機能と同様に、/admin/user にアクセスした場合にUserContollerの各処理を呼び出すように設定します。

※下記、L10を参照

routes/admin.php
  use App\Http\Controllers\Auth\AuthenticatedSessionController;
  use App\Http\Controllers\Auth\ConfirmablePasswordController;
  use App\Http\Controllers\Auth\EmailVerificationNotificationController;
  use App\Http\Controllers\Auth\EmailVerificationPromptController;
  use App\Http\Controllers\Auth\NewPasswordController;
  use App\Http\Controllers\Auth\PasswordController;
  use App\Http\Controllers\Auth\PasswordResetLinkController;
  use App\Http\Controllers\Auth\RegisteredUserController;
  use App\Http\Controllers\Auth\VerifyEmailController;
+ use App\Http\Controllers\Admin\UserController;
  use Illuminate\Support\Facades\Route;

④表示用の画面ファイルを作成する。

resources/views/admin/user に ユーザー一覧画面、編集画面の2画面を作成します。

resources/views/admin/user/index.blade.php
@extends('adminlte::page')

@section('title', 'ユーザー一覧')

@section('content_header')
    <h1>ユーザー一覧</h1>
@stop

@section('content')
    {{-- 完了メッセージ --}}
    @if (session('message'))
        <div class="alert alert-info alert-dismissible">
            <button type="button" class="close" data-dismiss="alert" aria-hidden="true">
                ×
            </button>
            {{ session('message') }}
        </div>
    @endif

    {{-- 検索 --}}
    <div class="container" th:fragment="search">
		<form action="{{ route('admin.user.index') }}" method="get">
			<div class="form-group form-inline input-group-sm">
			    <label for="id" class="col-md-2 control-label">ユーザーID</label>
			    <input type="text" class="form-control col-md-5" id="id" name="id" placeholder="ユーザーID" value="{{ @$search_keywords['id'] }}">
			</div>
            <div class="form-group form-inline input-group-sm">
			    <label for="user_name" class="col-md-2 control-label">ユーザー名</label>
			    <input type="text" class="form-control col-md-5" id="user_name" name="user_name" placeholder="ユーザー名" value="{{ @$search_keywords['user_name'] }}">
			</div>
            <div class="form-group form-inline input-group-sm">
			    <label for="email" class="col-md-2 control-label">メールアドレス</label>
			    <input type="text" class="form-control col-md-5" id="email" name="email" placeholder="メールアドレス" value="{{ @$search_keywords['email'] }}">
			</div>
			<div class="text-center">
				<button class="btn btn-sm btn-outline-secondary" type="submit">検索</button>
			</div>
		</form>
		<hr>
	</div>

    {{-- 新規登録画面へ --}}
    {{-- <a class="btn btn-primary mb-2" href="{{ route('admin.user.create') }}" role="button">新規登録</a> --}}

    <div class="card">
        <div class="card-body">
            <table class="table table-bordered">
                <thead>
                    <tr>
                        <th>ユーザーID</th>
                        <th>ユーザー名</th>
                        <th>メールアドレス</th>
                        <th style="width: 70px"></th>
                    </tr>
                </thead>
                <tbody>
                    @foreach ($users as $user)
                        <tr>
                            <td>{{ $user->id }}</td>
                            <td>{{ $user->name }}</td>
                            <td>{{ $user->email }}</td>
                            <td>
                                <a class="btn btn-primary btn-sm mb-2" href="{{ route('admin.user.edit', $user->id) }}"
                                    role="button">編集</a>
                                <form action="{{ route('admin.user.destroy', $user->id) }}" method="post">
                                    @csrf
                                    @method('DELETE')
                                    {{-- 簡易的に確認メッセージを表示 --}}
                                    <button type="submit" class="btn btn-danger btn-sm"
                                        onclick="return confirm('削除してもよろしいですか?');">
                                        削除
                                    </button>
                                </form>
                            </td>
                        </tr>
                    @endforeach
                </tbody>
            </table>
        </div>
    </div>
@stop

resources/views/admin/user/edit.blade.php
@extends('adminlte::page')

@section('title', 'ユーザー編集')

@section('content_header')
    <h1>ユーザー編集</h1>
@stop

@section('content')
    @if ($errors->any())
        <div class="alert alert-warning alert-dismissible">
            {{-- エラーの表示 --}}
            <ul>
                @foreach ($errors->all() as $error)
                    <li>{{ $error }}</li>
                @endforeach
            </ul>
        </div>
    @endif

    {{-- 編集画面 --}}
    <div class="card">
        <form action="{{ route('admin.user.update', $user->id) }}" method="post">
            @csrf @method('PUT')
            <div class="card-body">
                <div class="form-group">
                    <label for="name">名前</label>
                    <input type="text" class="form-control" id="name" name="name"
                        value="{{ old('name', $user->name) }}" placeholder="名前" />
                </div>
                <div class="form-group">
                    <label for="price">メール</label>
                    <input type="text" class="form-control" id="email" name="email"
                        value="{{ old('email', $user->email) }}" placeholder="メールアドレス" />
                </div>
            </div>
            <div class="card-footer">
                <div class="row">
                    <a class="btn btn-default" href="{{ route('admin.user.index') }}" role="button">戻る</a>
                    <div class="ml-auto">
                        <button type="submit" class="btn btn-primary">編集</button>
                    </div>
                </div>
            </div>
        </form>
    </div>
@stop

⑤コントローラーに表示処理を実装する。

編集時のリクエスト、バリデーションはコントローラーファイルにて記載します。

※下記、参照に上書きする

app/Http/Controllers/Admin/UserController.php
<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\Reserve;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\Rule;

class UserController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\View\View
     */
    public function index(Request $request)
    {
        // 検索処理の準備
        $query = User::query();
        $search_keywords = array();

        // リクエストの検索キーに値がセットされていたらSQL抽出条件として追加する
        if ($request->filled('id')) {
            $query->where('id', '=', $request->input('id'));
            $search_keywords['id'] = $request->input('id');
        }

        if ($request->filled('user_name')) {
            $query->where('name', 'LIKE', "%{$request->input('user_name')}%");
            $search_keywords['user_name'] = $request->input('user_name');
        }

        if ($request->filled('email')) {
            $query->where('email', 'LIKE', "%{$request->input('email')}%");
            $search_keywords['email'] = $request->input('email');
        }

        // 設定した抽出条件+ソートをしてデータを取得する
        $users = $query->orderBy('id', 'asc')->get();

        // 動作確認用デバッグログ
        Log::debug($query->toSql());

        return view('admin.user.index', compact('users', 'search_keywords'));
    }

    /**
     * Display the specified resource.
     *
     * @param  \App\Models\User  $user
     * @return \Illuminate\View\View
     */
    public function show(User $user)
    {
        return view('admin.user.show', compact('user'));
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  \App\Models\User  $user
     * @return \Illuminate\View\View
     */
    public function edit(User $user)
    {
        //Log::info('user info', ['user' => $user]);
        //Log::info('user info', ['user' => $user->toArray()]);
        return view('admin.user.edit', compact('user'));
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Models\User  $user
     * @return \Illuminate\Http\RedirectResponse
     */
    public function update(Request $request, User $user)
    {
        $request->validate([
            'name' => ['string', 'max:255'],
            'email' => ['email', 'max:255', Rule::unique(User::class)->ignore($user->id)],
            //'password' => 'required',
        ]);

        $user->update($request->all());
        return redirect()->route('admin.user.index')->with('message', 'updated');
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Models\User  $user
     * @return \Illuminate\Http\RedirectResponse
     */
    public function destroy(User $user)
    {
        // 削除ユーザーの予約をすべて削除
        Reserve::where('user_id', $user->id)->delete();

        // ユーザーを削除
        $user->delete();
        return redirect()->route('admin.user.index')->with('success', 'deleted');
    }
}

動作確認

・管理画面にて/admin/user にアクセスし、一覧画面が表示されるかを確認する。

・https://localhost/registerから登録したユーザーが一覧画面に表示されるかを確認する。

・編集ボタンでユーザー情報の編集ができるかを確認する。

---