Laravelで作成したアプリをheroku(Free)にデプロイした時の手順とつまづいた様々なこと

##■前書き

ローカル環境(Homestead + vagrant)でLaravelアプリを開発していたのですが、デプロイを一度もしたことが無くちゃんとデプロイ出来るか試しにやってみたところ案の定様々な障害にぶち当たったのでその手順とつまづいた箇所をまとめたいと思います。

##■実際に行ったデプロイの手順(ざくーり）
本題はつまづいた箇所なのでここはざっくりとしか紹介しません。
#####1.LaravelアプリをGitで管理する
#####2.リモートリポジトリをGitHubに設定
#####3.Herokuアカウントを開設 + アプリ作成 + ローカルでProcfile作成
#####4.HerokuでPipline作成 + GitHubを連携
#####5.ClearDB(mysql)のAdd-onを追加
#####6.必要な環境変数の設定
#####7.ローカルの変更をローカルリポジトリへコミット
#####8.ローカルリポジトリからリモートリポジトリへプッシュ
#####9.Pipline上でデプロイ
#####10.マイグレーション実行
#####11.必要なマスターデータ(初期から入れておきたいデータ)のシーディング


ここら辺を参考にしました。
http://qiita.com/shosho/items/c38731c7db29767b3dcc
http://qiita.com/niiyz/items/07c07ebd7cd8993dc28e
http://qiita.com/sutara79/items/a173b969474d9f5afe1b
http://qiita.com/mokamoto/items/ecd4d5bb52523b779b02
https://schoo.jp/class/4063 (これの1と2を特に)

##■つまづいた様々なこと
ここからが本題です。上記手順で進める中で案の定めっちゃつまづきまくったのでその内容をまとめます。

###**1./vendorフォルダ内に変更を加えていた**
自分の場合はチャット用にPusherを利用していて（Pusher：https://pusher.com/）
以下のエラーのためにvendorディレクトリ内の一部を修正していました。

「LaravelでPusherを使おうとしたらClass Pusher not found的なエラーが出てきたので対処法をメモ」
http://qiita.com/Yorinton/items/dad82a12a22477561011

そのため.gitignoreファイルに```/vendor```と記述した状態でデプロイした場合、
上記の修正が反映されずエラーが発生してしまっていました。

基本的には```/vendor```内のファイルには変更を加えないのが理想だと思うのですが、
止むを得ず変更した場合は**.gitignoreファイルから/vendorを削除**してから```git push```する必要があります。 


###**2.DB関連の環境変数がどこを見ればいいか分からない><**
ローカルで開発する場合は.envに設定している環境変数ですが、セキュリティの関係上.envファイルはgitでソースコントロールすべきではありません。

そのため環境変数をheroku上で設定する必要があるのですが、
以下のようなDB関連の環境変数がどこを見ればいいか分からず苦労しました。。
・DB_USERNAME
・DB_PASSWORD
・DB_DATABASE
・DB_HOST
・DB_PORT

それぞれ参照する場所を記載します。
ClearDBのAdd-onを追加している場合アプリの管理画面に以下のような表示がされますのでクリックします。
<img width="622" alt="スクリーンショット 2017-09-01 23.35.51.png" src="https://qiita-image-store.s3.amazonaws.com/0/121811/b932be6d-432c-cc17-8a20-4486adb0fc00.png">
すると以下のような画面が別タブで開きます。

<img width="1272" alt="スクリーンショット 2017-09-01 23.37.59.png" src="https://qiita-image-store.s3.amazonaws.com/0/121811/4f700c04-8dc8-f6ae-457f-15cf06670304.png">

**①DB_DATABASE**
上の表の一番左にある「Name」のところに記載されている文字列が```DB_DATABASE```になります。

**②DB_USERNAME / DB_PASSWORD**
上記の画像のNameの文字列をクリックして「Endpoint Information」というタブを開くとDB_USERNAME / DB_PASSWORDに該当する値が表示されています。

**③DB_PORT**
DB_PORTは3306でOKです。

**④DB_HOST**
これが一番見つけるのに苦労しました。
これが設定されていないとデプロイしてもDBを使う場面で接続エラーが発生してしまいます。
こちらは「Backups&Jobs」タブをクリックした時に表示される表の「Server」の列に表示されている文字列を入れるとうまくいきました。

###**3.マイグレーションのコマンドはどこで実行すればいいの？？**
環境変数の設定がうまくいって、「そうだ！マイグレーションをしよう！」と思ったのですが、```php artisan migrate```コマンドをどこで打てばいいかわかりませんでした。
やり方は２つあるようです。


**①自分のローカルのターミナルから実行**
HerokuCLを自分のターミナルにインストールしている前提です。
（HerokuCLのインストール方法：https://devcenter.heroku.com/articles/heroku-cli）

やり方といっても簡単で、
まず、

```
heroku run bash
```

を実行すると、herokuのコマンドラインに入れます。
そこで

```
php artisan migrate
```
を実行すればOKです。

**②herokuの管理画面から実行**
アプリの管理画面を開くと右上に「More」と書いてあるところがあるので、そこをクリックして「Run Console」をクリックします。
<img width="236" alt="スクリーンショット 2017-09-02 1.15.25.png" src="https://qiita-image-store.s3.amazonaws.com/0/121811/1f3adcb3-f8c9-4d6f-345f-184b34908991.png">
すると画面下にコマンドを実行できる画面が現れるので、あとはmigrateコマンドを打ち込んで「Run」ボタンをクリックするだけです。
<img width="1272" alt="スクリーンショット 2017-09-02 1.16.28.png" src="https://qiita-image-store.s3.amazonaws.com/0/121811/6dbab1ee-b8fc-ba87-8d86-4814a1a44b82.png">


###**4.マイグレーションでえらいエラーが出るんですが、、**
**①キー設定したカラムの文字数制限がローカルと異なる**
ローカルと同じマイグレーションファイルでマイグレートコマンドを実行すると以下のようなエラーが出ました。

```
[Illuminate\Database\QueryException]                                                                                                            
  SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes (SQL: alter table `linked_soci  
  al_accounts` add unique `linked_social_accounts_provider_id_unique`(`provider_id`))
```
キーを設定しているカラムのバイト数が大きすぎる！！767バイト以下じゃないとダメ！と言われています。
ただ、文字コードがutf8の場合1文字3バイトなので文字数制限は255文字までのはず。僕の場合はちゃんと255文字という制限を入れているのに何故？？という感じでした。

調べて見ると、mysqlで文字コードが```utf8mb4```となっている場合1文字4バイトとなり、文字数制限が191文字までになってしまうようです。
これはmysql6系からのデフォルトらしいのですが、Laravelでは```config/database.php```を見ると、文字コードが```utf8mb4```と設定されています。

ローカルではエラーにならなかったのに、本番ではエラーになる意味がよくわかりませんが、とりあえずキーが設定されいているカラムの文字数制限を191文字に変更することで対応出来ました。

**②新しいマイグレーションファイルを作って文字制限を変更してもダメ**
上記のエラーについて、最初は新しいマイグレーションファイルを作成して文字数制限を255から191に変更する処理を```up()```メソッド内に記述して実行しましたがダメでした。
どうやら最初にテーブルを作成する時点でエラーが発生してしまうようで、後から別のマイグレーションファイルで変更を加えようとしてもそこまでマイグレートが到達しないみたいです。

気乗りしませんでしたが、最初にテーブルを作成する処理を記述したマイグレーションファイルを編集してデプロイし直した上で再度マイグレートコマンドを実行しました。

**③マイグレーションが途中で止まった時にやり直そうとしても別のエラーが出ちゃう**
上記のようなエラーによって、中途半端なところでマイグレーションが止まってしまい、```rollback```や```reset```をしてもどうにもならない、ということが発生してしまいました。

これは、すでに実行済みのマイグレーションファイルが```migrations```というテーブルで管理されており、```migrations```テーブルに登録されたファイルは実行されず、登録されていないファイルだけ実行しようとするため変な不整合(特に外部キーを設定している場合など)が起きてしまっていることが原因でした。

対策としては
①```migrations```テーブル以外のテーブルを全てmysqlにログインして削除(drop table ***)
②その後```migrations```テーブル内のレコードを全て削除(delete from migrations)する
ことで不整合を解消することが出来ました。

※最初の試しデプロイだったので、色々無茶できましたが、すでにユーザーがいる状態ではこの方法は危険すぎるのでやらない方がいいと思います。

**④ローカル環境では上手くいくのに、Heroku上でエラーが出る。。**
単純に本番のDBにデータが入ってなかったために、データが入って無いだけでした。。
データを入れる + データが無ければ初期値を入れる処理を入れることで無事解決！

**⑤Herokuだとページの読み込みがめっちゃ遅い**
アセットコンパイルを行っていないのが原因でした。
`package.json`を以下のように記述することでビルドの際に自動でアセットコンパイルしてくれるようになります。
※一番下の行

```json
  "scripts": {
    "dev": "npm run development",
    "development": "node node_modules/cross-env/dist/bin/cross-env.js NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "watch": "node node_modules/cross-env/dist/bin/cross-env.js NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "watch-poll": "npm run watch -- --watch-poll",
    "hot": "node node_modules/cross-env/dist/bin/cross-env.js NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
    "prod": "npm run production",
    "production": "node node_modules/cross-env/dist/bin/cross-env.js NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "heroku-postbuild": "npm run production"
  }
```
※参照「Laravel + Vue.jsアプリをHerokuで動かしたら読み込みがやたら遅かった件への対応(原因調査〜対策〜結果)」
http://qiita.com/Yorinton/items/b362d1be09011f81e29c

##■学び
沢山エラーが出て途中諦めかけましたが、
①エラー文言をちゃんと読んで、原因を特定した上で一つずつ対応して行けばなんとかなるということ
②実際にいろんなエラーを体験してそれを解消する過程で色々調べることで新しい知識を習得できること（やってみることが大事）
を学びました。

今回の体験が誰かのお役に少しでも立つことが出来れば幸いです。