#前回のパート
前回は、Authの導入とマイグレーションファイルを作成し
今回のTodoアプリで使用するテーブルの作成まで行いました
前回のパートはこちら→Vue CLI × Laravel × VuetifyでCSSいらずの爆速開発でTodoリストを作る part2
今回は、全てのページで使うヘッダーの作成と認証周りの実装をやっていきます
#ヘッダーコンポーネントの作成
全てのページで共通で使うヘッダーを作成していきます
Vuetifyで実装しますので、Vuetifyを使用しない方は自作での実装をしてください
まず、client/components
にHeader.vue
を作成し下記を追加してください
<template>
<v-card color="grey lighten-4" flat height="200px" tile>
<v-toolbar dense>
<v-app-bar-nav-icon></v-app-bar-nav-icon>
<v-toolbar-title>Todo-List</v-toolbar-title>
<v-spacer></v-spacer>
<router-link to="/signup">
<v-btn icon>
<v-icon>mdi-account</v-icon>
</v-btn>
</router-link>
<router-link to="/todo">
<v-btn icon>
<v-icon>mdi-align-horizontal-left</v-icon>
</v-btn>
</router-link>
<router-link to="/login">
<v-btn icon>
<v-icon>mdi-login</v-icon>
</v-btn>
</router-link>
<v-btn icon>
<v-icon>mdi-logout</v-icon>
</v-btn>
</v-toolbar>
</v-card>
</template>
templateのみのシンプルな物です
各<v-btn>
を<router-link>
で囲み、会員登録やログインやログアウト、Todoページのリンクを設定しています
全てVuetifyになります
詳しく知りたい方はこちらを参照ください→こちら
これでヘッダーの用意は終わりです
#会員登録の実装
まずはVue側でフォームの実装をしていきます
client/components
にRegister.vue
を作成してください
Register.vue
にを下記の様に下記を追加してください
<template>
<div>
<Header />
<div class="main-container">
<v-form v-model="valid"> //・・・①
<v-text-field v-model="form.name" :rules="nameRules" label="Name" required></v-text-field> //・・・②
<v-text-field v-model="form.email" :rules="emailRules" label="E-mail" required></v-text-field>
<v-text-field v-model="form.password" :rules="passwordRules" label="Password" required type="password"></v-text-field>
<v-text-field v-model="form.password_confirmation" :rules="repasswordRules" label="Confirm Password" required type="password"></v-text-field>
<v-btn small>submit</v-btn>
</v-form>
</div>
</div>
</template>
<script>
import Header from './Header';
export default {
components: {
Header
},
metaInfo: { //・・・③
title: '会員登録',
htmlAttrs: {
lang: 'ja'
}
},
data () {
return {
form : {
name: '',
email: '',
password: '',
password_confirmation: '',
},
nameRules: [
v => !!v || '名前を入力してください', //・・・④
],
emailRules: [
v => !!v || 'E-mailを入力してください',
v => /^\w+([.-]?\w+)*@\w+([.-]?\w+)*(\.\w{2,3})+$/.test(v) || 'E-mailを正しく入力してください' //・・・⑤
],
passwordRules: [
v => !!v || 'パスワードを入力してください',
v => v.length >= 8 || 'パスワードは8文字以上で入力してください' //・・・⑥
],
repasswordRules: [
v => !!v || 'パスワードの再入力を行ってください',
v => v == this.form.password || 'パスワードが一致しません' //・・・⑦
]
}
}
}
</script>
<style>
.main-container {
width: 500px;
margin: auto;
}
</style>
①ここは全てVuetifyになります
ここでは簡単な説明はしますが、もっと詳しく知りたい方は、こちらをご覧ください→こちら
②Vuetifyのフォームになります
:rules
この部分で下の④⑤⑥⑦のルールとバインディングしており、フロント側でのバリデーションを行っています
require
は入力必須を意味します
label
でフォームのラベル名に設定できます
②で設定しているものはどれも同じ要領です
次に設定しているバリデーションのルールについて軽く触れておきます
④入力の値が存在しているかどうか(未入力でないか)をチェックしています
⑤正規表現でEmailの形式かどうかをチェックしています
⑥パスワードが8文字以上で入力されているかをチェックしています
⑦passwordの入力値を一致しているかをチェックしています
③part1でインストールしたVue Metaです
ここでは、titleを【会員登録】としてlangをjaに設定しています
Vue Metaをこの様な設定を行うために使用します
これで、Vuetifyを使って簡単にフォームを用意できバリデーションまで行えました
次に会員登録機能の実装を行っていきます
#会員登録機能の実装(Laravel側)
まずは、routes/api.php
を開きルートを定義していきます
/register
は会員登録用のルート
/user
はログインをしているのかを常時チェックするために用意したルートになります(この後のVue側の実装で再度説明します)
<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
Route::post('/register', 'Auth\RegisterController@register')->name('register'); //追加
Route::get('/user', function(){ //追加
return Auth::user();
});
次にapp/Http/Controllers/Auth/RegisterCOntroller.php
を開いて下記を追加します
protected function registered(Request $request, $user) //追加
{
return $user;
}
registerd()
メソッドをオーバーライドすることで
登録処理をした際にUser情報を返却できる様に設定できます
この値を使って今後認証を行うので、上記を追加しました
このついでに
ログイン時にとログアウト時にも必要になる処理を先にやっておきます
app/Http/Controllers/Auth/LoginController.php
を開いて下記を追加してください
protected function authenticated(Request $request, $user) //追加
{
return $user;
}
こちらの追加の内容も、registerd()
メソッドのオーバーライドをした際と同じ理由になり
ログイン時にUserの情報を返却する様に設定しています
次にLoginController.php
でさらにloggedOut()
メソッドを追加してください
protected function loggedOut(Request $request)
{
$request->session()->regenerate();
return response('', 200);
}
こちらは、ログアウト時に呼ばれるメソッドになり
ログアウト時にセッションを再生成を行い、レスポンスを返す様にしてあります
上記3つの追加点については、本記事作成でも参考にさせて頂いたこちらの記事を参照してください→こちら
以上で会員登録に必要なLaravel側の処理の実装は終わりです(ログイン時とログアウト時の設定も行いました)
#会員登録処理(Vue側)
まずRegister.vue
に下記を追加してください
<template>
<div>
<Header />
<div class="main-container">
<v-form v-model="valid">
<v-text-field v-model="form.name" :rules="nameRules" :counter="10" label="Name" required></v-text-field>
<v-text-field v-model="form.email" :rules="emailRules" label="E-mail" required></v-text-field>
<v-text-field v-model="form.password" :rules="passwordRules" label="Password" required type="password"></v-text-field>
<v-text-field v-model="form.password_confirmation" :rules="repasswordRules" label="Confirm Password" required type="password"></v-text-field>
<v-btn small @click="register">submit</v-btn> //追加
</v-form>
</div>
</div>
</template>
<script>
import Header from './Header';
export default {
components: {
Header
},
metaInfo: {
title: '会員登録',
htmlAttrs: {
lang: 'ja'
}
},
created () {
const user = this.$store.getters['auth/user'];
if (user !== null) {
this.$router.push('/todo');
}
},
data () {
return {
form : {
name: '',
email: '',
password: '',
password_confirmation: '',
},
nameRules: [
v => !!v || '名前を入力してください',
],
emailRules: [
v => !!v || 'E-mailを入力してください',
v => /^\w+([.-]?\w+)*@\w+([.-]?\w+)*(\.\w{2,3})+$/.test(v) || 'E-mailを正しく入力してください'
],
passwordRules: [
v => !!v || 'パスワードを入力してください',
v => v.length >= 8 || 'パスワードは8文字以上で入力してください'
],
repasswordRules: [
v => !!v || 'パスワードの再入力を行ってください',
v => v == this.form.password || 'パスワードが一致しません'
]
}
},
methods: { //追加
async register() {
await this.$store.dispatch('auth/register', this.form);
this.$router.push('/todo');
}
}
}
</script>
<style>
.main-container {
width: 500px;
margin: auto;
}
</style>
①クリックイベントを追加しています
クリックすることでregister
メソッドを呼び出します
②このメソッドによって登録処理を実行します
厳密に言うと、登録処理をするアクションを呼び出しています(auth.jsについてはこの後実装します)
会員登録の処理後に、Todoページに遷移する様にしています
次に、register()
でdispatchしているauth.js
のregister
の実装をしていきます
import axios from 'axios';
const state = {
user: null //追加
}
const getters = {
user: state => state.user //追加
}
const mutations = {
setUser (state, user) { //追加
state.user = user;
}
}
const actions = {
async register({ commit }, data) { //追加
const response = await axios.post('/api/register', data)
commit('setUser', response.data);
},
async searchUser({ commit }) { //追加
const response = await axios.get('/api/user');
const user = response.data ? response.data : null
commit('setUser', user);
},
}
export default {
namespaced: true,
state,
getters,
mutations,
actions
}
import Vue from 'vue';
import App from './App.vue';
import router from './router/router';
import store from './store/store';
import vuetify from './plugins/vuetify';
import axios from 'axios';
import VueMeta from 'vue-meta';
Vue.config.productionTip = false
Vue.use(axios);
Vue.use(VueMeta, { refreshOnceOnNavigation: true });
const createApp = async () => { //追加
await store.dispatch('auth/searchUser');
new Vue({
router,
vuetify,
store,
render: h => h(App)
}).$mount('#app')
}
createApp(); //追加
一気にauth.jsの追加とmain.jsの一部追加を行いました
一つづ説明していきます
const state = {
user: null
}
stateでuserの情報を管理します
このアプリケーション内では、全てこのuserの値の有無を見てログイン認証やユーザー情報の所得を行います
const getters = {
user: state => state.user
}
stateのuserの情報を所得するgetterを定義しています
const mutations = {
setUser (state, user) {
state.user = user;
}
}
受け取ったデータをstateのuserに値をセットするミューテーションを定義しています
async register({ commit }, data) { //追加
const response = await axios.post('/api/register', data)
commit('setUser', response.data);
}
Laravel側のapi.php
で定義したregister
に対してpostしています
第二引数のdataはフォームに入力された値がv-modelでバインドされたdataの中身が渡されています
ここでの返り値として、先ほどオーバーライドしたregistered()
メソッドでの$userの値がresponseにセットされます
その値をsetUserに対してcommitしてstateのuserに値を設定しています
async searchtUser({ commit }) { //追加
const response = await axios.get('/api/user');
const user = response.data ? response.data : null;
commit('setUser', user);
}
Laravel側の実装の際にapi.php
にて定義した/user
のルートに対してアクセスをしています
/user
のルートはAuth::user()として認証しているユーザーの情報を返却する様に作りました
Auth::user()は認証していればユーザー情報が、認証されていなければnullが返ってきます
それを利用して、上記アクションでは/api/user
に対してリクエストをしてその戻り値(認証されていればユーザー情報、認証されていなければnull)を
変数responseに入れています
const user = response.data ? response.data : null;
で認証されていてresponseに値が入っていればその値を
認証されておらずnullが入っていればnullを変数userに入れています
そのuserをsetUserでcommitしてstateのuserに値を入れています
なのでstateのuserはログインしていればユーザー情報、ログインしていなければnullが常に入っている様にしています
あとはこれを常時実行するためにどうしているかと言うと、先ほど追加したmain.js
の追加部分になります
const createApp = async () => {
await store.dispatch('auth/searchUser');
new Vue({
router,
vuetify,
store,
render: h => h(App)
}).$mount('#app')
}
createApp();
ここでVueインスタンスが作られる際に毎回、createApp()
を実行することにより
auth.js
のsearchUser
アクションを実行しています
これにより、auth.js
のsearchUser
が毎回実行されることで
Laravelで定義した/user
にリクエストを投げ現在の認証情報を所得しauth.js
のsetUser
がcommitされ
stateのuserに値がセットされると言うことになります
created () {
const user = this.$store.getters['auth/user'];
if (user !== null) {
this.$router.push('/todo');
}
}
この部分でそのページにアクセスする度にcreated()
が実行され
auth.js
のgettersを利用してstateの現在のuser情報を所得し
ログインしていれば/todo
のページへ遷移する様に設定しています(ログインしていない場合はログインページが表示される)
ここまでの実装で
会員登録が行える様になりますので、フォームから入力して登録を実行してみてください
正常であれば、入力内容がDBに保存され登録処理ができます
#終わりに
今回はヘッダーのコンポーネントの作成と、会員登録機能の実装を一通り行いました
次回は、今回登録した内容を利用してログインができる様に、ログイン機能の実装をやっていきます
次のパートはこちら→Vue CLI × Laravel × VuetifyでCSSいらずの爆速開発でTodoリストを作る part4