Fippiyのプログラム学習内容アウトプットBlog

日々の学習内容をアウトプットして振り返りを実施する。

Laravel開発、ユーザー情報を編集する【1】ログインユーザーの情報を更新できるようにする

現在作成中のアプリではログインした上でサービスを扱うことができます。

しかし、ユーザー情報が扱えるのは新規登録とログインのみとなっており、特に登録後にユーザー情報を確認したり編集する…という機能は一切できない状態です。

今回はユーザー自身の情報を扱う機能を追加していきます。

今回の目的

ユーザー情報の詳細を表示させる

ユーザー情報の編集を行えるようにする

なぜやるか

一度登録すると、それ以降ユーザーの名前・パスワード等が一切変更できない状態となっているため、ユーザー情報の操作を行えるようにするため

やりたいこと

ユーザーの詳細情報を表示するページを用意したい

ユーザー情報を編集できるようにしたい

やったこと

マイページトップと関連メニューを準備する

マイページトップにユーザーデータを表示する

ユーザー情報編集ページを作成する

ユーザー名を編集する

パスワードを編集する

実施内容

マイページトップを作成する

トップページを作成する

以前、ログインユーザー情報は簡易的にヘッダに名前を表示させました。

しかし、詳細情報を見るには直接DBを見るしか方法がなく、ユーザー自身が登録内容を見る手段がそもそもない状況です。

まずは、ユーザーが登録した情報を見えるようにしました。

コントローラー

# ~/app/Http/Controllers/UserController.php

public function index()
{
$auth = Auth::user();
return view('user.index',[ 'auth' => $auth ]);
}

ログインユーザー情報を取得しています。これを元にビューで表示させます。

 

ビュー 

# ~/resources/views/user/index.blade.php

f:id:Fippiy:20190418140322p:plain

user.indexビュー

user.indexとしてユーザーのトップページを作成しました。

他のindexサイトをベースにしています。

ユーザー情報をまずは表示するために、とりあえずUserテーブルの全要素を出力しています。

関連してパンくずリストやマイページ用のメニューも作成しています。

 

# 表示ビュー

f:id:Fippiy:20190418140353p:plain

ビュー表示

ログインユーザーの情報を表示するサイトとなりました。

 

クラス名とスタイルシートを編集して見た目を調整します。

# ~/resources/views/user/index.blade.php

@section('content')
<div class="index-content">
<div class="books-list">
<div class="books-list__title mypage-color">
マイページトップ
</div>
<div class="book-table">
<div class="book-table__profile-list">
<div class="profile-group">
<div class="profile-group__title">ユーザー名</div>
<div class="profile-group__element">{{$auth->name}}</div>
</div>
<div class="profile-group">
<div class="profile-group__title">ユーザーID</div>
<div class="profile-group__element">{{$auth->id}}</div>
</div>
<div class="profile-group">
<div class="profile-group__title">メールアドレス</div>
<div class="profile-group__element">{{$auth->email}}</div>
</div>
<div class="profile-group">
<div class="profile-group__title">登録日時</div>
<div class="profile-group__element">{{$auth->created_at}}</div>
</div>
<div class="profile-group">
<div class="profile-group__title">最終更新日時</div>
<div class="profile-group__element">{{$auth->updated_at}}</div>
</div>
</div>
</div>
</div>
</div>
@endsection

最低限必要なものに絞り込みました。

 

# ビュー

f:id:Fippiy:20190419215634p:plain

ユーザー情報確認

スタイル調整実施後のビューです。これでマイページにアクセスすることで現在のユーザー情報が確認できるようになりました。

  

ユーザー情報を編集する

続いて、ユーザー情報を編集できるようにしていきます。

編集ページを作成する

ユーザー編集ページをまず作成します。

併せてユーザー名を編集できるフォームを用意します。

コントローラーedit

# ~/app/Http/Controllers/UserController.php

public function edit($id)
{
$auth = Auth::user();
return view('user.edit',[ 'auth' => $auth ]);
}

indexと同じですが…編集ページに渡すデータはユーザーデータがあれば表示できます。

 

ビュー

# ~/resources/views/user/edit.blade.php

@extends('layouts.layout')

@section('title', 'EditForm')

@section('stylesheet')
<link href="/css/menulist.css" rel="stylesheet" type="text/css">
<link href="/css/book-index.css" rel="stylesheet" type="text/css">
@endsection

@section('breadcrumbs')
<div class="book-header__breadcrumbs">
{{ Breadcrumbs::render('user.edit',$auth) }}
</div>
@endsection

@section('pagemenu')
@include('components.menu_mypage')
@endsection

@section('content')
<div class="index-content">
<div class="books-list">
<div class="books-list__title mypage-color">
ユーザー情報編集
</div>
@if (isset($msg))
<div class="books-list__msg">
<span>{{$msg}}</span>
</div>
@endif
<div class="book-new">
<form action="{{ route('user.update', $auth->id)}}"
method="post" enctype="multipart/form-data">
{{ csrf_field() }}
<input type="hidden" name="_method" value="PUT">
<div class="form-contents">
<div class="form-one-size">
<div class="form-input">
<div class="form-label">ユーザー名</div>
<div><input class="form-input__input" type="text" name="name"
value="{{$auth->name}}"></div>
</div>
</div>
</div>
<div class="form-foot">
<input class="send" type="submit" value="編集">
</div>
</form>
</div>
</div>
</div>
@endsection
index同様に他のeditページをベースに作成しました。
アクション{{ route('user.update', $auth->id)}}とすることで、編集処理へ移行するようにしています。
 
コントローラーupdate
# ~/app/Http/Controllers/UserController.php
public function update(Request $request, $id)
{
// 対象レコード取得
$auth = User::find($id);
// リクエストデータ受取
$form = $request->all();
// フォームトークン削除
unset($form['_token']);
// レコードアップデート
$auth->fill($form)->save();
return redirect('/user');
}
シンプルにデータを受け取って保存するのみです。
 
 

表示を確認します。

# ビュー

f:id:Fippiy:20190419222427p:plain

編集フォーム
名前を変更して編集ボタンを押すことで名前を変更することができるようになりました。

カラム編集手順を確認する

ユーザー名は単純にフォーム入力を上書で完成しました。
残る編集項目はメールアドレスとパスワードです。
そのまま編集してみる
ユーザー名と同じ手順でまずはフォームを追加して実装してみました。
…たしかにフォームさえ追加すれば更新はできます。
しかし、以下の問題点があります。
  • メールアドレス:データは更新されるが、メール送付による認証がない
  • パスワード:平文で保存されてしまう、確認フォームに関係なく更新される
これらの対処が必要となります。
メールアドレス編集手順
メール送付認証をつける前であれば、単純にデータ更新で終了していたかもしれませんが、更新時だけ認証しないのもおかしな話なので、認証システムを実装したいところです。
しかし、すでに新規登録とパスワードリセットでメール送信は使っているので、これらをヒントに送信機能をつけられないかを検討します。
※メールアドレス変更の実装は後で行うこととしました。
 
パスワード編集手順
パスワードの暗号化と入力フォーム内のデータ一致確認が必要です。
編集=リセットという考えでリセットフォームを利用するという方法もありますが、ログインできているのにわざわざリセット申請するのも変な気がしました。
処理としては新規登録時に行われているので、設定を確認すれば実装できるかもしれません。

パスワードを変更する

パスワード編集機能を実装しましたが、後ほど実装方法を変更します。詳しくは次記事をごらん下さい。

新規登録処理を確認する
まずは新規登録時に行われている処理を確認しました。
# ~/app/Http/Controllers/Auth/RegisterController.php
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
}
 
ユーザー新規作成を行っているコードです。
ここでパスワードをハッシュとしています。これを使えば平文は回避できますね。
 
後はパスワード入力と確認項目の一致をチェックする方法です。
# ~/app/Http/Controllers/Auth/RegisterController.php
protected function validator(array $data)
{
return Validator::make($data, [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
]);
}
同じコントローラーでvalidatorによるチェックをしています。
ここで'confirmed'として、同一データかをチェックしています。
この2つがあれば、パスワードに関しては編集フォームで対応できそうです。
 
パスワード編集を実装する
新規登録の処理を参考にパスワード編集機能を実装します。
アップデート処理を変更
# ~/app/Http/Controllers/UserController.php
public function update(Request $request, $id)
{
// バリデーションルール
$this->validate($request, User::$editRules);
// 対象レコード取得
$auth = User::find($id);
// リクエストデータ受取
$form = $request->all();
// フォームトークン削除
unset($form['_token']);
// パスワード処理
// ハッシュ化
if (isset($form['password'])) {
$form['password'] = Hash::make($form['password']);
}
// レコードアップデート
$auth->fill($form)->save();
return redirect('/user');
}
バリデーション設定
# ~/app/User.php
public static $editRules = array(
'password' => 'confirmed'
);
 
 バリデーションでパスワードフォーム入力の内容確認を実施し、その後パスワードのハッシュ化をして保存…という形に変更しました。
 
 
これでまずパスワードに関しては意図した変更が実施されるようになりました。
 
バリデーションのパターンを考える
しかし、このままでは2つのパスワード入力欄一致は確認できますが、入力文字数制限がないため何文字でも対応できてしまいます。
そしてもう一つ、編集フォームで入力していないデータは更新対象から外す…といったことも実装したいと考えました。
 
未入力項目を更新対象から外す
まずは、入力データがない時は対象から外すという方法を実装してみました。
public function update(Request $request, $id)
{
// バリデーションルール
$this->validate($request, User::$editRules);
// 対象レコード取得
$auth = User::find($id);
// リクエストデータ受取
$form = $request->all();
// フォームトークン削除
unset($form['_token']);
// フォーム要素の評価
foreach ($form as $key => $value) {
// nullの場合更新対象から除外する
if($value == null) {
unset($form[$key]);
}
}
// パスワード処理
// ハッシュ化
if (isset($form['password'])) {
$form['password'] = Hash::make($form['password']);
}
// レコードアップデート
$auth->fill($form)->save();
return redirect('/user');
}
受け取ったフォームデータをforeachで取り出し、要素毎に判定を実施。
valueがnullの場合は、データ処理前にキーごと削除するといった処理を入れました。
 
これでパスワード未入力時は除外されます、ユーザー名やパスワードを空欄にした場合も更新対象から除外されます。

実装方法を見直す

ここまでで、ユーザー名とパスワード変更は対応できるようになりました。
しかしパスワードについてはいくつか問題が残ってしまいました。
 
  • バリデーションに文字数制限を入れていない為1文字から設定できてしまう
  • 8文字以上設定にすると0文字で更新対象外とならなくなる(入力必須)
  • 現在のパスワードを確認せずに新パスワードでいきなり更新される
 
これらについては次で考え方の整理をし、実装を見直していきます。