【個人開発】Laravel + Vue.js でボードゲームカフェのレビューができるSPAのサイトを作成しました！

## 概要
都内のボードゲームカフェの検索とレビューができるサイトをローンチしました！

https://bodoge-cafe-reviews.com

テストユーザーは以下で入れます！
test@gmail.com
password

GitHubで実際のソースコードも見れます！
https://github.com/K-taiga/boardgame-reviews
## サービスについて
今回このレビューサイトの開発をしようと思ったのは自分のプログラミングスキルの向上がメインです！

実際に開発をする前と終わった後では明らかに成長をしたなと思います:muscle:！

普段はサーバーサイドがメインなので、
インフラからフロントエンドまでやったことでかなり知識の裾野を広げることができたと思います。

また最近、少しずつボードゲーム人気が高まってきて自分自身も好きなのでそういうブームに
このサイトが一助になれたらいいなと思って作りました:pray:！

コロナが収束したらまたボードゲームカフェに遊びに行けるようになりたいですね！

ではこれから具体的な内容について解説していきます。
（エンジニア歴一年目なので何かあればご指導ご鞭撻お願いします、、、）

## アプリケーション概要
サーバーサイドはLaravelでAPIの実装、
フロントエンドはVueを利用してSPA(Single Page Application)にしています。

## 機能一覧

 * ボードゲームカフェの一覧を表示する
<a href="https://gyazo.com/48730684f51b8e072dc79106d3959b27"><img src="https://i.gyazo.com/48730684f51b8e072dc79106d3959b27.gif" alt="Image from Gyazo" width="1000"/></a>

 * ボードゲームカフェのサジェスト検索をする
<a href="https://gyazo.com/1a8768dcbb36af919783829df6a20edf"><img src="https://i.gyazo.com/1a8768dcbb36af919783829df6a20edf.gif" alt="Image from Gyazo" width="1000"/></a>
 
一覧で表示するときに取ってきた全てのボードゲームカフェの情報から、
名前だけサジェスト用に別の配列で持っておいて検索できるようにしています。

 * 東京23区ごとのボードゲームカフェの一覧を表示する
 
<a href="https://gyazo.com/f4f2be20faf560832c30026562f6079f"><img src="https://i.gyazo.com/f4f2be20faf560832c30026562f6079f.gif" alt="Image from Gyazo" width="1000"/></a>

23区のidをルートパラメータから受け取り、それを元に絞り込みをしています

 * ボードゲームカフェを条件によってソートと絞り込みをする
<a href="https://gyazo.com/6e4482e68c3c7fc9306cc63c6a716855"><img src="https://i.gyazo.com/6e4482e68c3c7fc9306cc63c6a716855.gif" alt="Image from Gyazo" width="1000"/></a>
ソートと条件のoptionを算出プロパティで監視し、
変更があればLaravelのAPIを呼びそのパターンのSQLを発行し検索するようにしています
 * ボードゲームカフェをお気に入りに登録する（ログイン後のみ）
<a href="https://gyazo.com/3c2cebc9a7fdb6f5090f74a2bd9f0d29"><img src="https://i.gyazo.com/3c2cebc9a7fdb6f5090f74a2bd9f0d29.gif" alt="Image from Gyazo" width="1000"/></a>

お気に入りボタンを押すことでlikesテーブルにshop_idとuser_idの組み合わせで保存し、
その数を表示しています。

またお気に入りしたカフェはプロフィールのところから一覧で見ることができるようにしています
<img width="1147" alt="スクリーンショット 2020-04-02 17.28.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/362153/19167794-78cf-813d-5bb5-b822d744cc0c.png">


 * ボードゲームカフェにレビューをする（ログイン後のみ）
<a href="https://gyazo.com/48a4f89f6e4307b7acfa31f215db453b"><img src="https://i.gyazo.com/48a4f89f6e4307b7acfa31f215db453b.gif" alt="Image from Gyazo" width="1000"/></a>
レビューはログインしないとできないようにしています
またレビューの一覧はvue elementでスクロールするたびに読み込むようにしています。

 * 会員登録する
<img width="1184" alt="スクリーンショット 2020-03-31 21.45.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/362153/f840d745-c217-9fbb-835f-cd8b8b97b7a4.png">
 

 * 会員情報を編集する（ログイン後のみ）
 <a href="https://gyazo.com/00e32c0fe9123e90d1d4721659f7bf2e"><img src="https://i.gyazo.com/00e32c0fe9123e90d1d4721659f7bf2e.gif" alt="Image from Gyazo" width="1000"/></a>
 
プロフィール画像と認証情報を編集できるようにしています
プロフィール画像はS3のアイコン画像用のディレクトリにuser_idで保存し、変更があればupdateするようにしています

 * 退会をする
<a href="https://gyazo.com/d7bceaf443420e7412311c3e78877d71"><img src="https://i.gyazo.com/d7bceaf443420e7412311c3e78877d71.gif" alt="Image from Gyazo" width="1000"/></a>
認証情報のパスワードを入力することで退会できるようにしています（できればして欲しくないですが:cry:)

 * ログインする
 <a href="https://gyazo.com/a743de743d95b6757a07afbd7cf72aeb"><img src="https://i.gyazo.com/a743de743d95b6757a07afbd7cf72aeb.gif" alt="Image from Gyazo" width="1000"/></a>

 * ログアウトする（ログイン後のみ）
 <a href="https://gyazo.com/dd8afc730ffa04befa3fbf51895e7ed4"><img src="https://i.gyazo.com/dd8afc730ffa04befa3fbf51895e7ed4.gif" alt="Image from Gyazo" width="1000"/></a>
 
## インフラ構成

<img width="906" alt="スクリーンショット 2020-04-02 17.10.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/362153/c7621bd4-ae79-4669-2378-c3b22872ba68.png">


インフラはAWS Elastic Beanstalkを利用し、GitHubのdeployブランチにコードがpushされるとCircleCIで自動デプロイされるようにしています。

またユーザーの画像とボードゲームカフェの画像は、S3のディレクトリを分けて読み込むようにしています。

## バックエンド

### 技術要素
 * Laravel 6.10.1
 * Apache
 * MySQL

### 概要

バックエンドはLaravelでフロントからAjaxで送られてくるデータを処理するだけのWeb APIとして実装しています。

またモデルのアクセサで加工したものを$appendsプロパティにいれてフロント側にJSONデータで返すようにしています。

### ER図

![er.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/362153/c21a0850-d777-7c39-6916-2a4fb90cb749.png)

### データベース概要

ユーザーテーブルはLaravelのデフォルトのものにアイコン画像(S3のオブジェクトURL)を保存するカラムを追加しています。

お気に入り(likesテーブル)とレビュー(reviewsテーブル)についてはuserに対して1:Nのリレーションで作成しています。

ボードゲームカフェの画像は当初は複数可能にして表側でカルーセルで表示しようと思ったので別テーブルにしているんですが、
画像を拾ってくるのが大変だったので結局1:1にしてしまいました。

また東京23区の情報はマスターとして参照するためだけに登録をしています。

## フロントエンド

### 技術要素
 * Vue.js
 * Vuex
 * Vue Router
 * Vue element
 * Bulma

### 概要

状態管理にVuex, ルーティングにVue router,サーバーへのアクセスはaxiosで非同期で処理したのをasync/awaitでキャッチして同期的に処理をすることでSPAを実現しています。

機能一覧にあるログイン後にできる機能についてはvue routerのナビゲーションガードで、
URLを直打ちしても飛ばないようにしています

またSPAなので最初のロード時に遅くなるのを防ぐために、webpackでviewごとに分割し遅延ローディングするようにしています。


### デザイン

デザインについてはCSSのフレームワークであるBulmaをCDNで利用するのではなくnpmでインストールし、気になるところは個人的に修正しています。

また動きのある部分(ログイン/ログアウト時のトースト等)はvue elementを用いて実現しています。

## 反省点

本当に色々ありすぎますが、インフラ周りの知識もないままTerraformでCI/CD環境を構築することにこだわりすぎて1ヶ月近く無駄にしてしまったり（結局できなかった、、、　次こそは！）
設計とかちゃんと考えずに作り出してしまってエラーが絶えなかったです、、、

エラーで詰まったりしたらずっとそれに執着するんじゃなくて、
進められるとこを進めていけばよかったです

あと詰まったら公式ドキュメントを熟読！以上！


## 最後に
作ったのは自分一人ですが、前の会社の同期やいつももくもく会をしているエンジニア仲間の方にレビューやアドバイスをしてもらったので完成させることができました（まだ実装したい機能は追加します、、、）！

本当にありがとうございました:pray:！！

この記事を読んで個人開発やってみようかなって思える人が増えたら嬉しいです！
コロナで外に出れない分、プログラミングしましょ〜！！！！！