【実践日記】「写真共有アプリを作る(Laravel×Vue)」 チュートリアル2日目(2019/01/17~21)

# やること
全16回「写真共有アプリを作ろう」の学習記録第2回です。
Qiita経由で見つけた下記URLを参考に手を動かします。

[Vue + Vue Router + Vuex + Laravelで写真共有アプリを作ろう (2 アプリケーションの設計](https://www.hypertextcandy.com/vue-laravel-tutorial-application-design)

***ツールのバージョン***

|Node|npm|Vue.js|Vue Router|Vuex|PHP|Laravel|
|---|---|---|---|---|---|---|
|10.7.0|6.4.1|2.5.21|3.0.2|3.0.1|7.2.10|5.7.19|

# 目的
「0からアプリを完成させる流れ（アプリケーションの設計）」を経験して知見を獲得し、
その後の`オリジナルアプリ作成`に生かすこと(2019/01/16に設定)

# 写真共有アプリ完成までの流れ（全16回）
   1. イントロダクション【済(1/16)】
   2. アプリケーションの設計　←今ここ（1/17～1/21)
   3. SPA開発環境とVueRouter
   4. 認証API
   5. 認証ページ
   6. 認証機能とVuex
   7. 認証機能とVuex Part.2
   8. エラーハンドリング
   9. 写真投稿API
   10. 写真投稿フォーム
   11. 写真一覧取得API
   12. 写真一覧ページ
   13. 写真詳細ページ
   14. コメント投稿機能
   15. いいね機能
   16. エラーハンドリング

# 今回やったこと
# SPAのアーキテクチャ
## 通信パターンの特徴
* 「普通の」Webアプリケーション
	* ①ブラウザが画面要求(GET)またはデータ送信(POST)に対してさーばはHTMLを返却
	* ②ブラウザはそのHTMLを描写して画面を構築する。ここまででワンセット。
	* 上記の動きを繰り返すのが通常のWebページ
* SPA(Single Page Application)
	* ① ブラウザは最初画面要求、サーバはHTMLを返却、ブラウザはそのHTMLを描写して画面を構築
	* ② その後、ブラウザからAjaxでデータの要求/送信が行われ、サーバからJSONデータが返却される、ブラウザは受け取ったJSONデータを使用しJavaScriptによって画面の一部を書き換える
	* ③ つまり、SPAは本来的な意味での「画面繊維」は発生しないのである

#実装する機能一覧
>データベースとURLを設計するために、写真共有アプリの機能を洗い出します。
	* 写真の一覧を表示する
	* 写真を投稿する（会員のみ）
	* 写真にいいねを付ける（会員のみ）
	* 写真からいいねを外す（会員のみ）
	* 写真からコメントを追加する（会員のみ）
	* 写真に付けられたいいねの数を表示する
	* 写真に付けられたコメントを表示する
	* 会員登録する
	* ログインする
	* ログアウトする（会員のみ）

# データベース設計
## 必要なテーブル
* photosテーブル

|列名|型|PRIMARY|UNIQUE|NOT NULL|FOREIGN|
|---|---|---|---|---|---|
|id|VARCHAR(255)|★|★|★||
|user_id|INTEGER|||★|→users(id)|
|filename|VARCHAR(255)|||★||
|created_at|TIMESTAMP|||||
|updated_at|TIMESTAMP|||||

* commentsテーブル

|列名|型|PRIMARY|UNIQUE|NOT NULL|FOREIGN|
|---|---|---|---|---|---|
|id|SERIAL|★|★|★||
|photo_id|VARCHAR(255)|||★|→photos(id)|
|user_id|INTEGER|||★|→users(id)|
|content|TEXT||||★||
|created_at|TIMESTAMP|||||
|updated_at|TIMESTAMP|||||

* likesテーブル

|列名|型|PRIMARY|UNIQUE|NOT NULL|FOREIGN|
|---|---|---|---|---|---|
|id|SERIAL|★|★|★||
|photo_id|VARCHAR(255)|||★|→photos(id)|
|user_id|INTEGER|||★|→users(id)|
|created_at|TIMESTAMP|||||
|udated_at|TIMESTAMP|||||

* usersテーブル（Laravelにデフォルトで用意されている）

|列名|型|PRIMARY|UNIQUE|NOT NULL|FOREIGN
|---|---|---|---|---|---|
|id|SERIAL|★|★|★||
|name|VARCHAR(255)|||★||
|email|VARCHAR(255)||★|★||
|password|VARCHAR(255)|||★||
|remember_token|VARCHAR(255)|||||
|email_verified_at|TIMESTAMP|||||
|created_at|TIMESTAMP|||||
|updated_at|TIMESTAMP|||||

# ER図
※テキストで表現する方法を模索中

# Web APIのURL設計
## WebAPIとは？
Ajaxでデータ要求/送信を受け取ってJSONデータを返却するサーバサイドのプログラムをWebAPI（または単なるAPI）と呼びます。SPAの場合はこのWeb APIについてもURLを設計する必要があります。

# 普通のWebページ(マルチページアプリケーション)とWebAPIの違い
## (使用できる)HTTPメソッドの種類が違う
* マルチページアプリケーション
	* GET
	* POSTの2種類
* WebAPI
	* GET
	* POST
	* PUT
	* PATCH
	* DELETE

## なぜ上記のような違いが出るのか？
### マルチアプリケーションの場合
>マルチページアプリケーションはサーバーへのリクエスト発行をアンカーリンク(`<a>`)とフォーム送信(`<form>`)に頼っています。アンカーリンクはGETリクエストを発行しますし、フォーム要素の`method`属性はGETとPOSTしかサポートしていません。

### WebAPIの場合
>WebAPIはAjaxによってリクエストを発行するので上記の制約はありません。HTTPの仕様として定義されているメソッドはすべて使用できるというわけです。具体的には以下の5種類のHTTPメソッドを使うことが出来ます.

## メソッドの種類
|メソッド|意味|
|---|---|
|GET|リソースの取得|
|GET|リソースの新規作成|	
|PATCH|リソースの一部変更|
|PUT|リソースの置き換え|
|DELETE|リソースの削除|
> 「リソース」というのは少し抽象的な表現ですが、「ユーザー」「写真」「商品」「ツイート」などリクエストにより操作したい対象のデータを指します。

# WebAPIのURL設計
>* 使用できるHTTPメソッドの違いはURL設計にも影響します。WebAPIの場合は使えるHTTPメソッドをフル活用した設計の考え方をするのが一般的です。

# URL設計の具体例
## マルチアプリケーションの場合
>具体例で考えてみましょう。あるアイテムの新規作成、編集、削除のURLを設計するとします。マルチアプリケーション流に考えると以下のようになるでしょう。

```
POST / items / create # 新規作成
POST / items / update # 編集
POST / items / dekete # 削除
```

>データの処理を依頼するためのメソッドがPOSTしかないので、ざっくり画面を要求するだけの時はGET、それ以外のデータ処理を要求するときはPOSTとして、データ処理の要求内容はURLのパスで表現するという考え方です。

## それに対して、WebAPIの場合
>このケースをWebAPI流に考えると以下のようになります

```
POST /items     # 新規作成
PATCH /items   # 編集
DELETE / items # 削除
```
>「itemをDELETEする」のように、***URLが目的語でHTTPメソッドが動詞***という形式になっています。データ処理の要求内容をHTTPメソッドで表現できるからこそ可能な設計ですね。

# URL一覧
>上記の説明を踏まえて、写真共有アプリで必要なWebAPIのURLは以下のとおりです。★マークがついているURLは認証済みでないとアクセスできません。

|URL|メソッド|認証|内容|
|---|---|---|---|
|/api/photos|GET||写真一覧取得|
|/api/photos|POST|★|写真投稿|
|/api/photos/{写真ID}|GET||写真詳細取得|
|/api/photos/{写真ID}/like|PUT|★|写真 いいね追加|
|/api/photos/{写真ID}/like|DELETE|★|写真 いいね解除|
|/api/photos/{写真ID}/comments|POST|★|写真 コメント追加|
|/api/register|POST||会員登録|
|/api/login|POST||ログイン|
|/api/logout|POST|★|ログアウト|
|/api/user|GET||認証ユーザー取得|

>	* 分かりやすいようにWebAPIの頭にはすべて`/api`を付けています。
	* いいね数やコメント内容は写真一覧または詳細データに含みます。
	* いいねの付け外しを`PUT`と`DELETE`で表現しました。外すのが`DELETE`なのはいいとして付けるのがなぜ`PUT`かというと、まず同じ人間
が同じ写真にいいねを何個も付けることは現実的な仕様として考えにくいので新規作成を意味する`POST`は不自然だと思いました。またいいねはONかOFFの状態しかなく、一部だけ変更することはないので`PATCH`も不自然です。仮にいいねを付けるリクエストを同じ写真に繰り返し行っても、置き換えを表す`PUT`であれば意味的に1個しかつかなそうな感じがするので`PUT`を採用しました。

>*  POSTがいいかPUTがいいかというような議論はあくまでURL設計を単体で見たときに分かりやすいか、美しいかを言ってるにすぎません。
   * HTTPメソッドの選択などのURL設計とプログラムの実装内容は関係がないことに注意してください。
   * 結局URLとそれに応答するプログラムはルート定義で恣意的に決めるのですから。
   * 論理的に不自然なURLを選択したからといってプログラムが正しく動作するかは別問題です。

# API以外
>API以外にサーバサイドで用意する必要があるURLは以下のとおりです。

|URL|メソッド|認証|内容|
|---|---|---|---|
|/|GET||最初にHTMLを返却する|
|/photos/{写真ID}/download|GET||写真をダウンロード|

# フロントエンド
>さて、最後に画面側のURLも載せておきます。
こちらはフロントエンド（Vue Router）で実現します。

|URL|内容|
|---|---|
|/|写真一覧ページ|
|/photos/{写真ID}|写真詳細ページ|
|/login|ログイン・会員登録ページ|

# おわり
今回はここまで

# 参考資料
[Webを支える技術 -HTTP, URI, HTML,そしてREST](https://www.amazon.co.jp/dp/4774142042/)
[HTTPの教科書](https://www.amazon.co.jp/dp/479812625X/)

# 次回やること
>次の章からコードを書いていきます。
まずはSPAプロジェクトの作成からVue Routerの導入まで進みます。

[Vue + Vue Router + Vuex + Laravelで写真共有アプリを作ろう(3)SPA開発環境とVue Router](https://www.hypertextcandy.com/vue-laravel-tutorial-setting-up-spa-project)