Laravelのアプリケーションのherokuへのデプロイ手順

# Laravelをherokuへデプロイする際の手順
簡単な流れはこんな感じ

1. Herokuアカウントの作成
2. applicationの新規作成
3. Heroku CLIのインストール
4. プロジェクトのディレクトリに必要なファイルを作成する
5. PostgreSQLの使用
6. 各種環境変数の設定
7. artisanコマンドの実行
8. 画像はbase64エンコード
9. debugを無効にしてproductionモードへ

# アカウント作成
下記URLよりアカウントを作成する
https://signup.heroku.com/login


# aplicationの新規作成
- アカウント作成後はapplicationを作成
- create new appを選択

![スクリーンショット 2019-09-21 22.29.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449626/d8093fb9-22ef-a7c3-2868-16177c57c673.png)

- App nameを今回はfugaapplicationとする
- Create appで作成完了
![スクリーンショット 2019-09-21 22.30.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449626/099f39ce-7aa7-b481-ddaf-8162d4d3ab8a.png)



# Heroku CLIインストール

```shell
# herokuインストール
$ brew tap heroku/brew && brew install heroku

# 下記コマンドでのインストールは公式非推奨
$ npm install -g heroku

# バージョン確認
$ heroku --version
```

## herokuへログイン
https://devcenter.heroku.com/articles/heroku-cli#getting-started

- 下記コマンドを打つと何かkeyを打つように問われるのでenterを押すとログイン認証のブラウザが開く、loginボタンを押してログイン完了

```shell
$ heroku login
```



# プロジェクトのディレクトリに必要なファイルを作成する
## heroku Procfileを作成

- プロジェクトディレクトリまで移動し、直下に**Procfile**ファイルを作成する
- 作成したProcfileを編集する

```shell
# ファイル作成
$ touch Procfile

# ファイル編集
$ vi Procfile

#  iでINSERTモードにし、下記内容を書き込む
$ web: vendor/bin/heroku-php-apache2 public/

# escでINSERT終了し、:wqで保存して閉じる
```

必要に応じてgitにコミット&プッシュする

```shell
$ git add -A .
$ git commit -m "Add Procfile"
$ git push heroku master
```
- herokuとgithubを連携し、**Automatic deploys**を許可しておけば、githubへのプッシュで一日に一回自動でデプロイされるようになる

![](https://i.imgur.com/X1FYp5P.png)


# PostgreSQLを用意
## アドオンの追加

- herokuのアドオンの**Heroku Postgres**の無料プラン(HobbyDev)を利用する
    - Resourcesタブからアドオンを検索し、追加する

![68747470733a2f2f692e696d6775722e636f6d2f474f4b6268666b2e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449626/b8982967-a39a-8375-1973-982319621bb9.png)




- herokuへログインし、ターミナル上で追加することもできる

```shell
$ heroku login

# 無料プランでDBを作成
$ heroku addons:create heroku-postgresql:hobby-dev

# アドオンが有効になったか確認
$ heroku pg:wait
```

# 環境変数設定
## heroku 環境変数の確認

- ローカル環境では`.env`ファイルを設定していたが、herokuでは`.env`ファイルを修正することなく、heroku用に環境設定することができる

```shell
# ログインした状態で設定状況を確認する
$ heroku login

# 全部の環境変数のキー:値を知りたい時
$ heroku config

# キーが分かるときその値のみ知りたい時
$ heroku config:get DATABASE_URL
```

## DATABASE用環境変数の設定

- **Heroku Postgres**のアドオンを追加した時点で自動で**DATABASE_URL**をkeyとして環境変数が保存される
- **DATABASE_URL**の値に基づき、それぞれの変数を設定する

```shell
# DB情報を確認
$ heroku config:get DATABASE_URL
# 出力結果
postgres://<ユーザ名>:<パスワード>@<ホスト>:5432/<DB名>

# この出力結果に基づき、次のように設定する
DB_CONNECTION: pgsql
DB_DATABASE : <DB名>
DB_HOST : <ホスト>
DB_USERNAME : <ユーザ名>
DB_PASSWORD : <パスワード>

## 環境変数設定するときのコマンド
$ heroku config:set DB_HOST=hostname

# コマンド実行後の実際の出力
postgres://tyfcuncgcimlpf:2d080624５４３４５４３４dfsf３４３４eefa76dbcf868a５４３w４５４３４５４５４b@ec2-54-５４1-５４３-５４４.compute-1.amazonaws.com:5432/dfiiks1５４３４５４３
DB_CONNECTION:     pgsql
DB_DATABASE:       dfiiks1５４３４５４３
DB_HOST:           ec2-54-５４1-５４３-５４４.compute-1.amazonaws.com
DB_USERNAME:       tyfcuncgcimlpf
DB_PASSWORD:       2d080624５４３４５４３４dfsf３４３４eefa76dbcf868a５４３w４５４３４５４５４b
```

- 画面上で、環境変数を追加することもできる
    - 追加したアドオンの画面を開いてsettingタグの**Database Credentials**でDB情報を確認できる
    ![68747470733a2f2f692e696d6775722e636f6d2f4932677a7142432e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449626/81d2206c-dae5-27b1-db59-4a8a8edcb1bd.png)
    
    - herokuの画面のsettingタグの**Config vars**で環境変数を柄できる
    ![68747470733a2f2f692e696d6775722e636f6d2f7a4741313055512e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449626/dbf4d5c0-bd90-7c0c-1bab-22fb219a9c2e.png)


# HerokuのPostgreSqlへの接続方法
下記コマンドで接続できる

```shell
# 接続
$ heroku pg:psql DATABASE_URL

# テーブル一覧表示
$ DATABASE=> \d

```
- ローカルでのセットアップができていない場合エラー文が出力される
    - セットアップ方法は別途Postgressqlを確認

```shell
# error 
▸ The local psql command could not be located. For help installing psql, see
▸ https://devcenter.heroku.com/articles/heroku-postgresql#local-setup
```


# マイグレーション
- herokuでのDB環境の設定ができてからマイグレーションを行う

herokuマイグレーションコマンド

```shell
# マイグレーションとシーディングを実行
$ heroku run php artisan migrate --seed

# (マイグレーションをやり直したい場合)
$ heroku run php artisan migrate:refresh --seed
```

### Class 'Faker\Factory' not found エラーが出たとき

- laravelでfakerを使用している場合は**fzaninotto/faker**をインストールする必要がある
https://github.com/laravel/framework/issues/14130

```shell
$ composer require fzaninotto/faker
```

この後マイグレーションで解決

# 画像はbase64エンコード

- 画像はstorageへの画像ファイル生成をして保存し、そのリンクをDBに格納していたが、herokuではファイルの生成が行えない、画像バイナリデータをDBに直接入れて対応する
    1. 画像バイナリを入れるカラム作成
    2. 画像バイナリを取得しbase64エンコードしてDBに格納
    3. base64の画像を表示

https://team-lab.github.io/skillup/step2/image_document.html
https://qiita.com/RitaChan/items/d59001430f50789c570f


## 画像を保存するカラムの型を変更
- 画像のリンクを保存していたカラムに対して、カラムの方を変更し、エンコードした長文を保存できるようにする
    - マイグレーションファイルを作成し、**string**型から**longText**型へ変更

```shell
$ php artisan make:migration change_{カラム名}_to_{テーブル名} --table={テーブル名}
```

**マイグレーションファイル例**

```php
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
          $table->longText('profile_img')->default('')->change();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
          $table->dropColumn('profile_img');
          $table->string('profile_img')->nullable()->change(); 
        });
    }
```

## 画像を表示するview変更例

**phpで書いた場合**

```html
// 変更前
<img class="c-img" src="/storage/profile_images/{{ $user->id }}.jpg" alt="プロフィール画像">

// 変更後
<img class="c-img" src="data:image/png;base64,{{ $user->profile_img }}" alt="プロフィール画像">
```

**vueで表示している場合**

```html
// 変更前
<img class="c-img" v-if="message.profile_img !== null" v-bind:src="'/storage/profile_images/' + message.from_user_id + '.jpg'" alt="プロフィール画像">
 
// 変更後
<img class="c-img" v-bind:src="'data:image/png;base64, '+ message.profile_img" alt="プロフィール画像">
```

## Controller変更例

```php
// 変更前
$user->profile_img = $request->profile_img->storeAs('public/profile_images', Auth::id() . '.jpg');

// 変更後
$user->profile_img = base64_encode(file_get_contents($request->profile_img));
```

以上で、DBにはエンコードされた長い文字列が保存され、表示されるようになる。

# アプリの情報を設定する
下記コマンド実行で設定完了

```shell
# デバッグを有効にする
$ heroku config:set DEBUGBAR_ENABLED=true

# キーを設定する
$ heroku config:set APP_KEY=$(php artisan key:generate --show)
```

# メール送信設定
mailtrapやgmailのSMTPを使用する際の設定値の確認は[こちら](https://qiita.com/KZ-taran/items/ffa60ac6353bc4dcc759)を参考に


## heroku メール用環境変数の設定

- DB設定と同様にheroku用に環境設定する
- 平文で送らないとエラーになるので、**MAIL_PORTは**587番

```shell
# ログインした状態で確認する
$ heroku login

# 全部の環境変数のキー:値を知りたい時
$ heroku config

# キーが分かるときその値のみ知りたい時
$ heroku config:get DATABASE_URL

# 環境変数のセッティング例
$ heroku config:set DB_HOST=hostname

# 設定内容(2019/8/23)現在
MAIL_DRIVER:       smtp
MAIL_FROM_ADDRESS: hogehoge.info@gmail.com
MAIL_FROM_NAME:    hogeapplication
MAIL_HOST:         smtp.gmail.com
MAIL_PASSWORD:     wcfghjkljhnsn
MAIL_USERNAME:     hogehoge.info@gmail.com
```

# 本番環境へ
## デバッグモードを無効に

```shell
$ heroku config:set DEBUGBAR_ENABLED=false
```

## production modeにする
- 下記コマンドでコンソールに出力されていた**vue deveropment**の文字も消える

```shell
$ npm run production
```