Laravelでログイン機能付きサイト作成 with XAMPP(3/4) ユーザー情報変更機能編

## 目標
**`Laravel`でブラウザ側からユーザー情報、テーブルのデータを変更できるようにする**

## 前回の記事
[Laravelでログイン機能付きサイト作成 with XAMPP(2/4)　認証機能の有効化編](https://qiita.com/kaitaku/items/13db4b60b7a4db6050af)

## ユーザー情報変更ページの作成
### 前準備
作りたいページを作成する前に、作業しやすいように環境を整える。

#### 大文字化の解除
現在、`css`によって小文字で入力したコードも大文字に変換して表示されている。
それを解除するには、`home.blade.php`の`<style>`から**`text-transform: uppercase;`**を削除すればOK。

#### トップページの変更
今回作成するサイトでは`(プロジェクト名)\resources\views\home.blade.php`をトップページとする。
`(プロジェクト名)\routes\web.php`を見てみると、http://127.0.0.1:8000/ にアクセスされた際、`welcome.blade.php`を返すルーティング処理が定義されていることがわかる。

```(プロジェクト名)\routes\web.php
Route::get('/', function () {
    return view('welcome');
});
```

なので、`home.blade.php`を返す定義に変更する。

```(プロジェクト名)\routes\web.php
Route::get('/', function () {
    return view('home');
});
```

そもそも、`home.blade.php`はログインが成功した際に表示される初めのページであり、ログインしてない状態では何も表示されない。
そのため、ログイン状態、非ログイン状態で表示する内容を変える必要がある。
実際に`home.blade.php`を見てみると、**`@guest`**というコードが見受けられる。
これは現在のユーザーが認証されたユーザーかどうかを判断する`blade`構文であり、`if`文の使い方をする。
つまり、`@guest`直下に非ログイン時に表示する内容、その次の`@else`でログイン時に表示する内容を定義することで、今回の課題が解決できる。
自分は以下のような内容にした。

```(プロジェクト名)\resources\views\home.blade.php
 <div class="card-header">
    @guest
        Laravel
    @else
        Hello, {{ Auth::user()->name }} !!
    @endguest
</div>
<div class="card-body">
    @if (session('status'))
        <div class="alert alert-success" role="alert">
            {{ session('status') }}
        </div>
    @endif
    <div class="links">
        @guest
            <a href="{{ route('login') }}">ログイン</a>
            <a href="{{ route('register') }}">登録</a>
            <a href="">検索</a>
        @else
            <a href="">ユーザー情報編集</a>
            <a href="">ユーザー検索</a>
            <a href="{{ route('logout') }}"
               onclick="event.preventDefault();
        document.getElementById('logout-form').submit();">
                ログアウト
            </a>
            <form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;">
                @csrf
            </form>
        @endguest
    </div>
</div>
```

以上の内容だと次のように表示される。

**非ログイン**
http://127.0.0.1:8000/

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218398/a92ecc76-acba-0f6f-fc61-a8313665c36f.jpeg" width="800px">

**ログイン状態**
http://127.0.0.1:8000/home

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218398/afb3e31f-c410-e438-4652-92a41582969e.png" width="800px">

現状、右上と中央にログイン機能、登録機能がそれぞれ存在しているので、中央のだけにしたい。
その場合、`(プロジェクト名)\resources\views\layouts\app.blade.php`の以下の部分をコメントアウトすることで目的が果たせる。

```(プロジェクト名)\resources\views\layouts\app.blade.php
<!-- Right Side Of Navbar -->
<ul class="navbar-nav ml-auto">
    <!-- Authentication Links -->
    @guest
        <li class="nav-item">
            <a class="nav-link" href="{{ route('login') }}">{{ __('Login') }}</a>
        </li>
        @if (Route::has('register'))
            <li class="nav-item">
                <a class="nav-link" href="{{ route('register') }}">{{ __('Register') }}</a>
            </li>
        @endif
    @else
        <li class="nav-item dropdown">
            <a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre>
                {{ Auth::user()->name }} <span class="caret"></span>
            </a>

            <div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown">
                <a class="dropdown-item" href="{{ route('logout') }}"
                   onclick="event.preventDefault();
                                 document.getElementById('logout-form').submit();">
                    {{ __('Logout') }}
                </a>

                <form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;">
                    @csrf
                </form>
            </div>
        </li>
    @endguest
</ul>
```
### ユーザー情報変更画面
ここからが本題。
まずはユーザー情報の変更を行うページから作成していく。
http://127.0.0.1:8000/home で下記画像の赤枠部をクリックするとユーザー情報を変更できるようにしたい。
構成としては、**`編集画面　→　編集確認画面　→　編集完了画面`** といった感じに。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218398/a1694519-3fd3-9df8-e279-5f3477820450.jpeg" width="800px">

コントローラーはターミナルで下記のコマンドを実行して作成する。

```
 $ php artisan make:controller User/EditController
```

http://127.0.0.1:8000/home から、今回作成する編集画面に行く際、現在のユーザーのIDなどを渡す必要がある。
それがないとテーブルから値が取得できず、作業ができない。
この問題を解決してくれるのが**`Auth::~`**などのコード。
認証機能を使用している場合、このような**`Auth::id()`**といった宣言することで、現在ログインしているユーザーの情報を出力できる。
あとは一般的なコントローラーの作成方法で完了。

```(プロジェクト名)\app\Http\Controllers\User\EditController.php
<?php

namespace App\Http\Controllers\User;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Auth;
use App\User;

class EditController extends Controller
{
    public function edit()
    {
        $Auth_data = Auth::id();
        $User_data = User::where('id', $Auth_data) -> first();
        return view('user/edit',['User' => $User_data]);
    }
}
```

表示するページはテーブルを利用して、各項目と現在の入力値を表示するだけ。

```(プロジェクト名)\resources\views\user\edit.blade.php
@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">
                    データの変更したい箇所に値を入力してください
                </div>
                <div class="card-body">
                    @if (session('status'))
                        <div class="alert alert-success" role="alert">
                            {{ session('status') }}
                        </div>
                    @endif
                    <div class="edit_table">
                        <form method="post" action="edit_check">
                            <table>
                                <tr>
                                    <th>ID</th>
                                    <th>NAME</th>
                                    <th>EMAIL</th>
                                    <th>WORKS_ID</th>
                                    <th>COMMENT</th>
                                    <th>CREATED_AT</th>
                                    <th>UPDATED_AT</th>
                                    <th>DELETE_FLAG(0=表示, 1=非表示)</th>
                                </tr>
                                <tr>
                                    <td>
                                        {{ $User['id'] }}
                                        <input type="hidden" value="{{ $User['id'] }}" name="edit_id">
                                    </td>
                                    <td><input type="text" value="{{ $User['name'] }}" name="edit_name"></td>
                                    <td><input type="text" value="{{ $User['email'] }}" name="edit_email"></td>
                                    <td><input type="text" value="{{ $User['works_id'] }}" name="edit_works_id"></td>
                                    <td><input type="text" value="{{ $User['comment'] }}" name="edit_comment"></td>
                                    <td>{{ $User['created_at'] }}</td>
                                    <td>{{ $User['updated_at'] }}</td>
                                    <td><input type="text" value="{{ $User['delete_flag'] }}" name="edit_flag"></td>
                                    <td><input type="submit" value="確認画面へ"></td>
                                </tr>    
                            </table>
                            @csrf
                        </form>
                    </div>
                    <div>
                        <input type="button" value="戻る" onclick="history.back()">
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
    
@endsection
```

表示用のページが作成できたら、遷移元の`home.blade.php`に今回作成したページへのリンクを追加。

```(プロジェクト名)\resources\views\home.blade.php
<a href="home/edit">ユーザー情報編集</a>
```

最後にルーティング処理を追記。

```(プロジェクト名)\routes\web.php
Route::get('/home/edit','User\EditController@edit');
```

以上のコードで作成されるページは次のようになる。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218398/528efabf-1efd-1631-ae0f-20e768beb079.jpeg" width="800px">



### ユーザー情報変更確認画面
続いて、変更画面で入力した内容を確認するページ、編集確認画面を作成していく。

先程と同様、下記のコマンドでターミナルからコントローラーを作成し、編集画面から`POST`で投げられた値を表示用のページに渡せるようにする。

```
 $ php artisan make:controller User/EditCheckController
```

```(プロジェクト名)\app\Http\Controllers\User\EditCheckController.php
<?php

namespace App\Http\Controllers\User;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\User;

class EditCheckController extends Controller
{
    public function check(Request $request)
    {
        $id = $request -> input('edit_id');
        $name = $request -> input('edit_name');
        $email = $request -> input('edit_email');
        $works_id = $request -> input('edit_works_id');
        $comment = $request -> input('edit_comment');
        $flag = $request -> input('edit_flag');
        $edit_database = User::where('id', $id) -> first();
        $edit_data = array(
            'id' => $id,
            'name' => $name,
            'email' => $email,
            'works_id' => $works_id,
            'comment' => $comment,
            'created_at' => $edit_database['created_at'],
            'updated_at' => $edit_database['updated_at'],
            'delete_flag' => $flag
        );
        return view('user/edit_check',['data' => $edit_data]);
    }
}
```

表示するページはテーブルを利用して、各項目と現在の入力値を表示するだけ。

```(プロジェクト名)\resources\views\user\edit_check.blade.php
@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">
                    以下の内容で登録します。よろしいですか?
                </div>
                <div class="card-body">
                    @if (session('status'))
                        <div class="alert alert-success" role="alert">
                            {{ session('status') }}
                        </div>
                    @endif
                    <div class="edit_table">
                        <form method="POST" action="edit_finish">
                            <table>
                                <tr>
                                    <th>ID</th>
                                    <th>NAME</th>
                                    <th>EMAIL</th>
                                    <th>WORKS_ID</th>
                                    <th>COMMENT</th>
                                    <th>CREATED_AT</th>
                                    <th>UPDATED_AT</th>
                                    <th>DELETE_FLAG(0=表示, 1=非表示)</th>
                                </tr>
                                <tr>
                                    <td>{{ $data['id'] }}</td>
                                    <td>{{ $data['name'] }}</td>
                                    <td>{{ $data['email'] }}</td>
                                    <td>{{ $data['works_id'] }}</td>
                                    <td>{{ $data['comment'] }}</td>
                                    <td>{{ $data['created_at'] }}</td>
                                    <td>{{ $data['updated_at'] }}</td>
                                    <td>{{ $data['delete_flag'] }}</td>
                                    <td><input type="submit" value="変更を反映する"></td>
                                    <input type="hidden" value="{{ $data['id'] }}" name="edit_id">
                                    <input type="hidden" value="{{ $data['name'] }}" name="edit_name">
                                    <input type="hidden" value="{{ $data['email'] }}" name="edit_email">
                                    <input type="hidden" value="{{ $data['works_id'] }}" name="edit_works_id">
                                    <input type="hidden" value="{{ $data['comment'] }}" name="edit_comment">
                                    <input type="hidden" value="{{ $data['delete_flag'] }}" name="edit_flag">                                  
                                </tr>    
                            </table>
                            @csrf
                        </form>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
    
@endsection
```

次のルーティング処理を追記して、http://127.0.0.1:8000/home/edit から http://127.0.0.1:8000/home/edit_check にエラーが表示されず遷移できるか確かめる。

```(プロジェクト名)\routes\web.php
Route::get('/home/edit_check','User\EditController@edit');
Route::post('/home/edit_check','User\EditCheckController@check');
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218398/8234fe26-fc84-e749-55ff-329aba215ee8.png" width="800px">

### 編集確認画面 → 編集画面
編集完了画面の作成に移る前に、確認画面から編集画面へ遷移する場合の処理を考える。
ここで重要なのは変更画面から確認画面へ移る際の値を渡すことだ。
早速、そのためのコードを追記していく。

`(プロジェクト名)\resources\views\user\edit_check.blade.php`の`</form>`の下あたりに、現在の値を渡すコードを記入。

```(プロジェクト名)\resources\views\user\edit_check.blade.php
    </form>
</div>
<div>
    <form method="post" action="edit">
        <input type="hidden" value="{{ $data['id'] }}" name="edit_id">
        <input type="hidden" value="{{ $data['name'] }}" name="edit_name">
        <input type="hidden" value="{{ $data['email'] }}" name="edit_email">
        <input type="hidden" value="{{ $data['works_id'] }}" name="edit_works_id">
        <input type="hidden" value="{{ $data['comment'] }}" name="edit_comment">
        <input type="hidden" value="{{ $data['delete_flag'] }}" name="edit_flag">
        <input type="submit" value="戻る">
        @csrf
    </form>
</div>
```

`(プロジェクト名)\app\Http\Controllers\User\EditController.php`に編集確認画面からデータを受け取れるよう追記。

```(プロジェクト名)\app\Http\Controllers\User\EditController.php
public function return_check(Request $request)
{
    $id = $request -> input('edit_id');
    $edit_data = User::where('id', $id) -> first();
    $name = $request -> input('edit_name');
    $email = $request -> input('edit_email');
    $works_id = $request -> input('edit_works_id');
    $comment = $request -> input('edit_comment');
    $flag = $request -> input('edit_flag');
    $User_data = array(
        'id' => $id,
        'name' => $name,
        'email' => $email,
        'works_id' => $works_id,
        'comment' => $comment,
        'created_at' => $edit_data['created_at'],
        'updated_at' => $edit_data['updated_at'],
        'delete_flag' => $flag
    );
    return view('user/edit',['User' => $User_data]);
}
```

最後にルーティング処理を追記して、実際に確認。

```(プロジェクト名)\routes\web.php
Route::post('/home/edit','User\EditController@return_check');;
```

#### 編集完了画面
今までの変更内容をデータベースに登録するファイルを作成していく。
上の2つと違って、データベースに登録するだけなので結構簡単。

いつも通りコントローラーを作成し、確認画面から送られてきた値をデータベースに保存する。

```
 $ php artisan make:controller User/EditFinishController
```

```(プロジェクト名)\app\Http\Controllers\User\EditFinishController.php
<?php

namespace App\Http\Controllers\User;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\User;

class EditFinishController extends Controller
{
     public function finish(Request $request)
    {
        $id = $request -> input('edit_id');
        $name = $request -> input('edit_name');
        $email = $request -> input('edit_email');
        $works_id = $request -> input('edit_works_id');
        $comment = $request -> input('edit_comment');
        $flag = $request -> input('edit_flag');
        $edit_data = User::where('id', $id) -> update([
            'name' => $name,
            'email' => $email,
            'works_id' => $works_id,
            'comment' => $comment,
            'delete_flag' => $flag
        ]);
        $User_data = User::where('id', $id) -> first();
        return view('user/edit_finish',['data' => $User_data]);
    }
}
```

表示するページは確認画面と同じく、テーブルを利用して、登録したデータを表示するだけ。

```(プロジェクト名)\resources\views\user\edit_finish.blade.php
@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">
                    以下の内容でユーザー情報を保存しました。
                </div>
                <div class="card-body">
                    @if (session('status'))
                        <div class="alert alert-success" role="alert">
                            {{ session('status') }}
                        </div>
                    @endif
                    <div class="edit_table">
                        <table>
                            <tr>
                                <th>ID</th>
                                <th>NAME</th>
                                <th>EMAIL</th>
                                <th>WORKS_ID</th>
                                <th>COMMENT</th>
                                <th>CREATED_AT</th>
                                <th>UPDATED_AT</th>
                                <th>DELETE_FLAG(0=表示, 1=非表示)</th>
                            </tr>
                            <tr>
                                <td>{{ $data['id'] }}</td>
                                <td>{{ $data['name'] }}</td>
                                <td>{{ $data['email'] }}</td>
                                <td>{{ $data['works_id'] }}</td>
                                <td>{{ $data['comment'] }}</td>
                                <td>{{ $data['created_at'] }}</td>
                                <td>{{ $data['updated_at'] }}</td>
                                <td>{{ $data['delete_flag'] }}</td>
                            </tr>    
                        </table>
                    </div>
                    <div>
                        <a href="/home">ホーム画面へ</a>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
    
@endsection
```

次のルーティング処理を追記して、完了画面が表示されるか確認したり、`phpMyAdmin`とかからデータが更新されているか確かめたりする。

```(プロジェクト名)\routes\web.php
Route::get('/home/edit_finish','User\EditController@edit');
Route::post('/home/edit_finish','User\EditFinishController@finish');
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218398/c476eece-6340-e5ca-b845-bc55473256f4.png" width="800px">

## 次回の記事
今回はブラウザ側からログインしているユーザーのデータを変更できるページを作成した。
次回では、検索機能をもったページを作成していく。


## 参考資料
- [[PHP] Laravel でユーザー認証されている時のユーザー情報の値のとり方や、判定する関数など ｜ memocarilog](https://memocarilog.info/php-mysql/8749)
- [PHP - html tableの行ごとにformを作成｜teratail](https://teratail.com/questions/54864)