【Laravel+Vue.js】アプリ制作の記録⑦DB連携(会員登録/ログイン機能)

はじめに

現在Laravel+Vue.jsでのアプリ制作の記録です。

この記事ですることは以下です。(かなり手探りで制作しています。)

Vue.jsでのDBへの追加・編集・削除。

一番シンプルに実装できそうな会員登録/ログイン機能でまずはDBへの追加に挑戦します。

アプリ制作するならマストで越えなければいけない壁。頑張ります。

※前回までの記録。

【Laravel+Vue.js】アプリ制作の記録①設計

【Laravel+Vue.js】アプリ制作の記録②プロジェクト作成

【Laravel+Vue.js】アプリ制作の記録③Vue Routerの実装

【Laravel+Vue.js】アプリ制作の記録④Vuexの実装

【Laravel+Vue.js】アプリ制作の記録⑤Vue.js側の作成

【Laravel+Vue.js】アプリ制作の記録⑥DBからのデータ取得

現状の確認

トップページの表示を確認。

CSS作成は無視。実装方法の把握に重きを置いて作っているのでこんな感じです。だいぶひどいです。笑

まずは、会員登録/ログイン画面はメインページと別で設けます。

また、ここで本格的にDB連携を目指していくので、LocalStorageを消します。

改修

上記の点を、DB実装の前にしていこうと思います。(初めてのLaravel+Vue.jsアプリ制作なので設計面が毎回変わりまくってます。。。)

Board.vueをVue Routerに取り込む

①router.jsの編集

import Vue from 'vue'
import VueRouter from 'vue-router'
import Register from './pages/Register.vue'
import Login from './pages/Login.vue'
import Board from './components/Board.vue' // add

Vue.use(VueRouter)

const routes = [
  // add
  {
    path: '/',
    component: Board
  },
  // up here
  {
    path: '/register',
    component: Register
  },
  {
    path: '/login',
    component: Login
  }
]

const router = new VueRouter({
  mode: 'history', 
  routes
})

export default router

②App.vueの編集

Board.vue関連の記述を削除。

RouterViewタグをmainタグの中に移動。

headerタグにrouter-linkタグでログイン/会員登録画面のリンクを追加。

<template>
  <div>
    <header>
      <h1><router-link to="/">My Note</router-link></h1> // edit
      <router-link to="Login">ログイン</router-link> // add
      <router-link to="Register">会員登録</router-link> // add
    </header>
    <main>
      <RouterView />
    </main>
    <footer>
      <div v-for="(list, index) in listing" :key="index">
        <h1>{{list.created_at}}</h1>
        <h1>{{list.title}}</h1>
      </div>
    </footer>
  </div>
</template>

<script>
export default {
  data() {
    return {
      listing :[]
    };
  },
  components: {
  },
  mounted() { 
    this.$http.get("/api/list").then(response => {
      this.listing = response.data;
    });
  },
}
</script>

③Login.vueの編集

<template>
  <div>
    <h3>Login</h3>
  </div>
</template>

④Register.vueの編集

<template>
  <div>
    <h3>Register</h3>
  </div>
</template>

http://127.0.0.1:8000/へアクセス。

Vue Routerが機能しているかも確認しつつ、こんな感じで3つのページに遷移できる状態になりました。(だいぶすっきりしました。)

LocalStorageの削除

index.jsの編集

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    lists:[
      {
        title: '',
        cards: []
      }
    ],
  },
  actions: {
    addlist(context, payload) {
      context.commit('addlist', payload)
    },
    removelist(context, payload) {
      context.commit('removelist', payload)
    },
    addCardToList(context, payload) {
      context.commit('addCardToList', payload)
    },
    removeCardFromList(context, payload) {
      context.commit('removeCardFromList', payload)
    },
  },
  mutations: {
    addlist(state, payload) {
      state.lists.push({ title: payload.title, cards:[] })
    },
    removelist(state, payload) {
      state.lists.splice(payload.listIndex, 1)
    },
    addCardToList(state, payload) {
      state.lists[payload.listIndex].cards.push({ body: payload.body })
    },
    removeCardFromList(state, payload) {
      state.lists[payload.listIndex].cards.splice(payload.cardIndex, 1)
    },
  },
  getters: {
    totalCardCount(state) {
      let count = 0
      state.lists.map(content => count += content.cards.length)
      return count
    },
  }
})

export default store

DB登録(会員登録/ログイン機能) part1

注意
後述の部分まで終えたのち、この教材のDB連携がテストコードありきなことに気付きました。ですのでこのpart1は制作過程の備忘録になります。もしアプリ制作の参考にされる際は次の記事を見ていただければ幸いです。

ここからが本番です。いよいよです。言い訳はできない位環境は整ってしまいました。

今回はVue + Vue Router + Vuex + Laravelで写真共有アプリを作ろう (4) 認証APIを大いに参考にします。※テストは割愛。

APIの実装

①RouteServiceProvider.phpの編集

protected function mapApiRoutes()
{
  Route::prefix('api')
    ->middleware('web') // edit
    ->namespace($this->namespace)
    ->group(base_path('routes/api.php'));
}

api.phpに記載するルート定義もweb.php同様に認証関連のミドルウェアなどが適用されるようにする。

②api.phpへ追記

Route::post('/register', 'Auth\RegisterController@register')->name('register');
Route::post('/login', 'Auth\LoginController@login')->name('login');
Route::post('/logout', 'Auth\LoginController@logout')->name('logout');

③コントローラの編集

RegisterControllerの編集

use Illuminate\Http\Request; // add

class RegisterController extends Controller
{
  ~~~~
  // add
  protected function registered(Request $request, $user)
  {
  return $user;
  }
}

LoginController.phpの編集

use Illuminate\Http\Request; // add

class LoginController extends Controller
{
  ~~~~
  // add
  protected function authenticated(Request $request, $user)
  {
    return $user;
  }
  protected function loggedOut(Request $request)
  {
    $request->session()->regenerate();
    return response()->json();
  }
}

ビューの作成

上述の教材5章・6章を参考にしています。

タブ切替だとコンポーネントが1つで済む。つまりURLが1つで済むことに気付きました。

一旦教材に倣ってLogin.vueのみで実装をしてみます。

①Login.vueの編集

<template>
  <div class="container--small">
    <ul class="tab">
      <li
        class="tab__item"
        :class="{'tab__item--active': tab === 1 }"
        @click="tab = 1"
      >Login</li>
      <li
        class="tab__item"
        :class="{'tab__item--active': tab === 2 }"
        @click="tab = 2"
      >Register</li>
    </ul>
    <div class="panel" v-show="tab === 1">
      <form class="form" @submit.prevent="login">
        <label for="login-email">Email</label>
        <input type="text" class="form__item" id="login-email" v-model="loginForm.email">
        <label for="login-password">Password</label>
        <input type="password" class="form__item" id="login-password" v-model="loginForm.password">
        <div class="form__button">
          <button type="submit" class="button button--inverse">login</button>
        </div>
      </form>
    </div>
    <div class="panel" v-show="tab === 2">
      <form class="form" @submit.prevent="register">
        <label for="username">Name</label>
        <input type="text" class="form__item" id="username" v-model="registerForm.name">
        <label for="email">Email</label>
        <input type="text" class="form__item" id="email" v-model="registerForm.email">
        <label for="password">Password</label>
        <input type="password" class="form__item" id="password" v-model="registerForm.password">
        <label for="password-confirmation">Password (confirm)</label>
        <input type="password" class="form__item" id="password-confirmation" v-model="registerForm.password_confirmation">
        <div class="form__button">
          <button type="submit" class="button button--inverse">register</button>
        </div>
      </form>
    </div>
  </div>
</template>

<script>
export default {
  data () {
    return {
      tab: 1,
      loginForm: {
        email: '',
        password: ''
      },
      registerForm: {
        name: '',
        email: '',
        password: '',
        password_confirmation: ''
      }
    }
  },
  computed: {
    apiStatus () {
      return this.$store.state.auth.apiStatus
    }
  },
  methods: {
    login () {
      console.log(this.loginForm)
    },
    async register () {
      await this.$store.dispatch('auth/register', this.registerForm)
      this.$router.push('/')
    },
    async login () {
      await this.$store.dispatch('auth/login', this.loginForm)
      if (this.apiStatus) {
        this.$router.push('/')
      }
    },
    async logout (context) {
      const response = await axios.post('/api/logout')
      context.commit('setUser', null)
    }
  }
}
</script>

②store/index.jsの編集

※後述のauth.jsをインポートします。

import auth from './auth' // add

~~~~
  // gettersの直後に追記
  modules: {
    auth
  }
})

 

②store/auth.jsの作成

ここも一旦教材に倣って進めます。

const state = {}
const getters = {}
const mutations = {}
const actions = {}

export default {
  namespaced: true,
  state,
  getters,
  mutations,
  actions
}

③CSRF対策

js/util.jsの作成、js/bootstrap.jsの編集

※教材通りなので割愛します。

ここでストップ!!
ここまで来て、先の章まで少し見渡してみました。すると、この教材のDB連携がテストコードありきなことに気付きました。ですのでここでこの教材を参考にするのはやめました。テストのハードルが高いため。。。)

おわりに

思わぬ挫折を味わいました。仕切り直して次回の記事で頑張ります。(長くなったので分けました。)

(ソースコードで追加、ここまでを記載するのに英語と日本語の入力変換が手間に感じたので今回はadd/up hereで記載しています。)

毎回設計が変わるのはLaravel+Vue.jsの連携方法がわからず、URL設計のしようがなかったことに起因しているかと思います。

このアプリ制作を終えたら反省会しながらより効率の良いアプリ制作方法を考えたいと思います。

参考

このアプリは数々のチュートリアル・教材を参考に制作しています。

参考にさせていただいた教材は以下でご紹介させていただきます。

参考教材

【Laravel x Vue.js】SPAクイズアプリケーションを作ってみよう!

Laravel(+Vue.js)でSNS風Webサービスを作ろう!

trello風todoタスク管理アプリを作成しよう!

Vue + Vue Router + Vuex + Laravelで写真共有アプリを作ろう

入門Laravelチュートリアル (2) ToDoアプリケーションの設計

公式ドキュメント(英文)

 

公式ドキュメント

その他参考(Qiitaなど)

コメントを残す