【コピペでOK】Laravelでユーザーテーブル編集と画像アップロード

# はじめに
画像アップロードって意外とめんどくさいので、コピペレベルで
実装できるサンプルを作りましたので、ご紹介いたします。

# こんな方におすすめ
・Laravelを一通り書籍等でおこない、画像処理に困っている方
・特に「PHPフレームワーク Laravel入門 単行本　掌田津耶乃」（青い表紙）でLaravelを学ばれた方　※この書籍では画像アップロードやり方が載ってない

# つくるもの
せっかくなので、デフォルトで作成される「users_table」に「thumbnail」カラムを追加して画像をアップできるようにしていきたいと思います。

要件
①「name」カラムをUpdate
②追加する「thumbnail」カラムをUpdate

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393193/428a0759-d46e-22e8-f882-af17287083e9.png)
![スクリーンショット 2019-06-23 15.06.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393193/30461e16-d788-9a75-a0a3-60ae75c96685.png)
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393193/de9aa62b-0c19-bb3d-8b4e-cf2a4527c018.png)

# 手順レシピ
1.準備
Laravelを新規構築

```
$ php artisan make:auth

$ php artisan migrate
```
registerからユーザー登録する
大量にテストデータを挿入したい場合は[シーディング](https://readouble.com/laravel/5.5/ja/seeding.html)を利用
※Userモデルは「make:auth」で自動的に生成されます
※Userテーブル以外の場合は各モデルを生成してください

```
$ php artisan make:migration add_thumbnail --table=users
```

```php:database/migrations/xxxx_xx_xx_xxxxxx_add_thumbnail.php
// 中略
public function up()
{
    Schema::table('users', function (Blueprint $table) {
        $table->string('thumbnail')->nullable();
    });
}
// 中略
public function down()
{
    Schema::table('users', function (Blueprint $table) {
        $table->dropColumn('thumbnail');
    });
}
```
registerで登録できなくなるのでnullをOKにしておきます。
register側でthumbnail登録できるようにしておけばnullableはなくてOK。

```
$ php artisan migrate
```

2.コントローラー実装

```
$ php artisan make:controller UserController
```

```php:app/Http/Controllers/UserController
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\User;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;
use Validator;
use Intervention\Image\ImageManagerStatic as Image;
use Illuminate\Support\Facades\Storage;

class UserController extends Controller
{
    public function index(Request $request){
        $authUser = Auth::user();
        $users = User::all();
    	$param = [
            'authUser'=>$authUser,
            'users'=>$users
    	];
    	return view('user.index',$param);
    }

    public function userEdit(Request $request){
        $authUser = Auth::user();
        $param = [
            'authUser'=>$authUser,
        ];
        return view('user.userEdit',$param);
    }

    public function userUpdate(Request $request){
        // Validator check
        $rules = [
            'user_id' => 'integer|required',
            'name' => 'required',
        ];
        $messages = [
            'user_id.integer' => 'SystemError:システム管理者にお問い合わせください',
            'user_id.required' => 'SystemError:システム管理者にお問い合わせください',
            'name.required' => 'ユーザー名が未入力です',
        ];
        $validator = Validator::make($request->all(),$rules,$messages);

        if($validator->fails()){
            return redirect('/user/userEdit')
                ->withErrors($validator)
                ->withInput();
        }

        $uploadfile = $request->file('thumbnail');

          if(!empty($uploadfile)){
            $thumbnailname = $request->file('thumbnail')->hashName();
            $request->file('thumbnail')->storeAs('public/user', $thumbnailname);

            $param = [
                'name'=>$request->name,
                'thumbnail'=>$thumbnailname,
            ];
          }else{
               $param = [
                    'name'=>$request->name,
               ];
          }

        User::where('id',$request->user_id)->update($param);
        return redirect(route('user.userEdit'))->with('success', '保存しました。');
    }
}
```
Auth::user()　→　認証ユーザー取得（今回はこっちを使用）
User::all()　→　ユーザー全て取得

2.ルーティング

```php:routes/web.php
// 追加
Route::get('/user', 'UserController@index')->name('user.index')->middleware('auth');
Route::get('/user/userEdit', 'UserController@userEdit')->name('user.userEdit')->middleware('auth');
Route::post('/user/userEdit', 'UserController@userUpdate')->name('user.userUpdate')->middleware('auth');
```

3.ビュー実装
共通レイアウトは初期で入っている「app.blade.php」を利用することとします

```html:resources/views/user/index.blade.php
@extends('layouts.app')
@section('title','ユーザー情報')
@section('content')
<div class="container">
  <table class="table table-striped table-hover">
  <thead>
  <tr>
    <th></th>
    <th>ID</th>
    <th>名前</th>
    <th>メールアドレス</th>
    <th></th>
  </tr>
  </thead>
  <tbody>
    <tr>
      <td>
        <div>
        @if(!empty($authUser->thumbnail))
        <img src="/storage/user/{{ $authUser->thumbnail }}" class="thumbnail">
        @else
        画像なし
        @endif
        </div>
      </td>
      <td>{{ $authUser->id }}</td>
      <td>{{ $authUser->name }}</td>
      <td>{{ $authUser->email }}</td>
      <td>
      <a href="{{ route('user.userEdit') }}" class="btn btn-primary btn-sm">編集</a>
      </td>
    </tr>
  </tbody>
  </table>
</div>	
@endsection
```

```html:resources/views/user/userEdit.blade.php
@extends('layouts.app')
@section('title','ユーザー情報変更')

@section('content')
<div class="container">
    @if (session('success'))
    <div class="alert alert-success">{{ session('success') }}</div>
	@endif

	<div class="topWrapper">
		@if(!empty($authUser->thumbnail))
			<img src="/storage/user/{{ $authUser->thumbnail }}" class="editThumbnail">
		@else
		画像なし
		@endif
	</div>

	<form method="post" action="{{ route('user.userUpdate') }}" enctype="multipart/form-data">
		{{ csrf_field() }}
			
		<input type="hidden" name="user_id" value="{{ $authUser->id }}">
		@if($errors->has('user_id'))<div class="error">{{ $errors->first('user_id') }}</div>@endif

		<div class="labelTitle">Name</div>
		<div>
			<input type="text" class="userForm" name="name" placeholder="User" value="{{ $authUser->name }}">
			@if($errors->has('name'))<div class="error">{{ $errors->first('name') }}</div>@endif
		</div>

		<div class="labelTitle">Thumbnail</div>

		<div>
			<input type="file" name="thumbnail">
		</div>

		<div class="buttonSet">
			<input type="submit" name="send" value="ユーザー変更" class="btn btn-primary btn-sm btn-done">
			<a href="{{ route('user.index') }}" class="btn btn-primary btn-sm">戻る</a>
		</div>
	</form>
</div>
@endsection
```

軽くCSSも作成したので、追加

```css:public/css/style.css
.topWrapper {
    width: 150px;
    margin: 0 auto;
}

.thumbnail {
    width: 30px;
    height: 30px;
    object-fit: cover;
    border-radius: 50%;
}

.editThumbnail {
    width: 150px;
    height: 150px;
    object-fit: cover;
    border-radius: 50%;
}

.buttonSet {
    margin: 30px 0 0 0;
    text-align: center;
}

.labelTitle {
    color: #006DD9;
    margin: 20px 0 5px 0;
}

input[class="userForm"] {
    width: 100%;
    padding: 5px 0 5px 10px;
    box-sizing: border-box;
    border: 1px solid #ccc;
    transition: 1s;
}
input[class="userForm"]:focus {
    background: #87ceeb;
}

.btn-done {
    background: #dc143c;
    border: 1px solid #dc143c;
}
.btn-done:hover {
    background: #cc1237;
    border: 1px solid #cc1237;
}

.error {
    font-size: 15px;
    font-weight: 100;
    color: #cc1237;
}
```

```html:resources/views/layouts/app.blade.php
<!--追加-->
<link href="{{ asset('css/style.css') }}" rel="stylesheet">
```

# シンボリックリンク作成
画像に関して、
アップロードされるところはstorageフォルダですが、
Laravelではpublicフォルダを参照されるので、
シンボリックリンクを作成する必要がある。

```
$ php artisan storage:link
```

# 動作確認
以上で画像アップロードができるようになったかと思います。