Laravelをやってみる③ プロフィール編集機能編

Laravel備忘録

いろいろとすっ飛ばしてるこのLaravelをやってみる記事ですが、①と②も是非ご覧ください。

Laravel備忘録 Laravelをやってみる① 設計編 Laravel備忘録 Laravelをやってみる② 検索機能編

最初に…

プロフィール編集機能をつけていきます。編集画面にて、名前の変更とプロフィール画像の追加ができるようにします。
Laravelでは勝手にusersテーブルが作られます。設計の段階ではそのままにしておきましたので、画像のパスを入れるカラムがありません。
マイグレーションで追加してあげましょう。ターミナルで以下を。

$ php artisan make:migration add_image_column_to_users_table --table=users

マイグレーションファイルが追加されるので、以下のように編集します。

public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->string('image')->nullable()->after('password');
        });
    }

public function down()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->dropColumn('image');
        });
    }

新規登録の際は画像をアップロードしないので、nullable()としておきます。また、このままだとupdated_atカラムの次に追加されるので、after(‘password’)とし、passwordカラムの次に追加するようにします。
downメソッドではimageカラムを消す処理を書きます。

$ php artisan migrate

ターミナルでマイグレートを行い、カラムが追加されたか確認しましょう。
できていたら、ロールバックできるかの確認。

$ php artisan migrate:rollback

カラムが消えている事を確認したら、再度以下を。

$ php artisan migrate

これでusersテーブルにimageカラムが追加されました。

お次は…

編集ページの画面モックです。
ここを表示するためには、Routingで

Route::get('/edit', 'UserController@index')->name('user.index');

/editにアクセスした時にUserControllerのindexメソッドを呼んであげます。

UserControllerのindexメソッドでは、viewを表示する処理をしますが、それと同時にユーザーの登録情報も一緒に渡してあげます。

public function index()
    {
        $authUser = Auth::user();

        return view('user.index', compact('authUser'));
    }

これにより、userディレクトリのindex.blade.phpにて$authUserでそのユーザー情報が取れるようになりました。

以下がviews/user/index.blade.phpです。

<form method="POST" action="{{ route('user.update') }}" enctype="multipart/form-data">
    @csrf

    <div class="form-group row">
        <label for="name" class="col-md-4 col-form-label text-md-right">{{ __('ニックネーム') }}</label>

        <div class="col-md-6">
            <input id="name" type="text" class="form-control @error('name') is-invalid @enderror" name="name" value="{{ $authUser->name }}" required autocomplete="name" autofocus>

            @error('name')
            <span class="invalid-feedback" role="alert">
                <strong>{{ $message }}</strong>
            </span>
            @enderror
        </div>
    </div>
    <div class="form-group row">
            <label for="inputFile" class="col-md-4 col-form-label text-md-right">プロフィール画像</label>
            <div class="input-group col-md-6">
                <div class="custom-file">
                    <input type="file" class="custom-file-input" id="inputFile" name="image">
                    <label class="custom-file-label" for="inputFile" data-browse="参照">選択かドロップ</label>
                </div>
                <div class="input-group-append">
                    <button type="button" class="btn btn-outline-secondary input-group-text" id="inputFileReset">取消</button>
                </div>
            </div>
        </div>
            @error('image')
            <span class="invalid-feedback" role="alert">
                <strong>{{ $message }}</strong>
            </span>
            @enderror
    <div class="form-group row">
        <div class="col-md-6 offset-md-6 prof-img">
            @if($authUser->image !== null)
                <img src="/storage/profile_images/{{ $authUser->image }}" class="button" style="object-fit: cover">
            @else
                <img src="../img/noimage.jpeg" class="button">
            @endif

        </div>
    </div>
    <div class="form-group row mb-0 mt-4">
        <div class="col-md-8 offset-md-2">
            <button type="submit" class="btn btn-info btn-block">
                {{ __('ニックネームと画像を変更する') }}
            </button>
        </div>
    </div>
</form>

ニックネーム欄に登録された名前が出ていると思います。

ここまでが初期画面です。
ここから、「変更する」ボタンを押した時の処理を書いていきます。

変更ボタン押下後の処理

まずRoutingですが、

Route::post('/update', 'UserController@update')->name('user.update');

このようにします。views/user/index.blade.phpのformのactionでroute(‘user.update’)を指定しています。POST送信されたときにここに処理がいきます。

UserControllerのupdateメソッドを書いていきます。

public function update(UserRequest $request)
    {

        $authUser = Auth::user();

        $authUser->name = $request->input('name');

        $uploadFile = $request->file('image');
        if (!empty($uploadFile)) {
            $thumbnailName = $request->file('image')->hashName();
            $request->file('image')->storeAs('public/profile_images', $thumbnailName);

            $authUser->image = $thumbnailName;
        }

        $authUser->save();

        return redirect('user/edit')->with('flash_message', '変更しました');

    }

今回はバリデーションをかけているため、引数がRequestではなく、UserRequestになっています。

$ php artisan make:request UserRequest

UserRequestクラスを作ったら以下のように修正します。

public function authorize()
    {
        return true;
    }

public function rules()
    {
        return [
            'name' => 'required|max:255',
            'image' => 'file|image|mimes:jpeg,png,jpg,gif|max:2048',
        ];
    }

ルールについてはhttps://readouble.com/laravel/6.x/ja/validation.htmlに書いてあります。

さて、UserControllerのupdateメソッドの説明に戻ります。

$authUser = Auth::user();

$authUser->name = $request->input('name');

上記コードは認証中のユーザー情報をもってきて、そこに入力された値を突っ込みます。

また、画像アップロードですが生PHPではややこしかったんですが、

$uploadFile = $request->file('image');
if (!empty($uploadFile)) {
   $thumbnailName = $request->file('image')->hashName();
   $request->file('image')->storeAs('public/profile_images', $thumbnailName);

   $authUser->image = $thumbnailName;
        }

上記コードは画像がアップされていたらの処理です。
アップされていたら、hashName()で、ファイル名をハッシュ化します。これは後述のstoreメソッドやstoreAsメソッド内でもしてくれますが、今回はDBに保存するために先にhash化しています。

ハッシュ化したものをstoreAsメソッドで保存します。storeメソッドはパス名のみ指定するのに対し、storeAsではファイル名も指定できます。

先ほどハッシュ化したファイル名を第2引数に渡します。そして、最後にusersのimageカラムにそのファイル名を上書きします。

save()を書いて、redirectします。
画像アップし、usersテーブルに保存されていたら成功です。