laradock/MySQL/Apache/laravel7/herokuのデプロイまでwindows10で（備忘録）

備忘録的にざっくりと書いていきます。

⚠️herokuでMySQLを使うためにはクレジットカード情報が必要です。
2020/8/16現在使用料は無料ですが、使いたくない場合はPostgreSQL推奨です。

参考にさせていただいた記事：

https://readouble.com/laravel/7.x/ja/
https://qiita.com/beer_geek/items/6e4264db142745ea666f
https://qiita.com/zuotianzhiye/items/513029d0b7b3dcaf9dc2
https://qiita.com/chatrate/items/b2703cb7854259bf343e

▼作業環境など
・エディタ: VScode
・ターミナル: VScode
・OS: Windows10
・ローカル開発環境: LaraDock
・サーバ: Apache
・フレームワーク: Laravel7*
・リモートテスト環境: heroku

## Dockerダウンロード
windows10でhyper-vの設定など。
こういった記事などを参考に進めていきます。
https://qiita.com/anikundesu/items/90a7706b434daed5e266
ダウンロード終了。

## ファイル構成
完成形のファイル構成はこうなります。

project-X
　├ laradock
　└ laravel
　　　└　Procfile

project-xをherokuのデプロイディレクトリにするように見えるブログを書かれている方もいましたが、僕の場合は laravel ディレクトリをデプロイしました。

## laradockのダウンロード

```
$ cd project-X
$ git clone https://github.com/Laradock/laradock.git
$ cd laradock
$ cp env-example .env
```

以前作成したlaradockのプロジェクトがあると、dockerを起動するとlocalhostにアクセスした際に過去のソースが表示されてしまいます。
今回ケースでは、project-xフォルダとは別のところにlaradockプロジェクトが作られていました。
portなど注意です。

サンプル

```
APP_CODE_PATH_HOST=../src # 名前はなんでもok
APP_CODE_PATH_CONTAINER=/var/www/html
DATA_PATH_HOST=~/.project-x-laradock/data # 過去のものと被らない様に


### Docker compose files ##################################

# Define the prefix of container names. This is useful if you have multiple projects that use laradock to have separate containers per project.
COMPOSE_PROJECT_NAME=TEST_laradock # 名前を付ける

### APACHE ################################################

APACHE_HOST_HTTP_PORT=8090 # 過去のものと被らない様に
APACHE_HOST_HTTPS_PORT=443
APACHE_HOST_LOG_PATH=./logs/apache2
APACHE_SITES_PATH=./apache2/sites
APACHE_PHP_UPSTREAM_CONTAINER=php-fpm
APACHE_PHP_UPSTREAM_PORT=9000
APACHE_PHP_UPSTREAM_TIMEOUT=60
APACHE_DOCUMENT_ROOT=/var/www/html/public # ドキュメントルート


### mysql ################################################

MYSQL_VERSION=5.7 #最新版は設定がめんどくさかったりするそう。
MYSQL_DATABASE=default #好きなものでもok
MYSQL_USER=default #好きなものでもok
MYSQL_PASSWORD=secret #好きなものでもok
MYSQL_PORT=3306
MYSQL_ROOT_PASSWORD=root #好きなものでもok


### PHP MY ADMIN ##########################################

# Accepted values: mariadb - mysql

PMA_DB_ENGINE=mysql

# Credentials/Port:

PMA_USER=default
PMA_PASSWORD=secret
PMA_ROOT_PASSWORD=secret
PMA_PORT=8092 # 使用するポートを書く

### WORKSPACE #############################################

### ～　中略　～　###

WORKSPACE_TIMEZONE="Asia/Tokyo" # mysqlのタイムゾーンを日本時間に。そのままだとUTCで now() がずれる


```

## Docker起動

```
$ pwd
laradock
$ docker-compose up -d --build workspace mysql php-fpm apache2 phpmyadmin # ← phpmyadminは必要なら。
```

## gitの設定

少し流れから脱線。windowsの場合は改行コードでエラーが出る可能性があるのでgitの設定を。

```
git config --global core.autocrlf false
```

この後に行う bash コマンドの後に改行コードでエラーが出てハマりました。

## MySQLの起動確認

https://qiita.com/Manabu-man/items/58d0f98a15656ed65136
こちらの記事を参考。

## laravelのダウンロード

```
$ pwd
laradock
$ docker-compose exec workspace bash
$ pwd
/var/www
$ cd html
$ composer create-project --prefer-dist laravel/laravel .
$ composer require barryvdh/laravel-debugbar --dev # 開発ツール
```

/laravel/.env を以下の様に

```
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=default
DB_USERNAME=default
DB_PASSWORD=secret
```

マイグレーションを実行

```
$ pwd
/var/www/html # dockerの中です
$ php artisan config:cache # 過去のキャッシュがあるかもしれないので削除
$ composer dump-autoload
$ php artisan migrate
```

データベースが作成されます。
http://localhost:8090 #8090は自分で設定したポートにしてアクセス。
アクセスすると、home画面が表示されるはず。

### CSSの編集

もしかしたら装飾の無いページが表示されるかも。
bootstrapを導入しました。

```
$ pwd
/var/www/html # dockerの中です
$ composer require laravel/ui
$ php artisan ui bootstrap
$ npm install
$ npm run dev
```

これでokのはず。
CSSの修正を随時反映したい場合は

```
$ npm run watch
```

## heroku準備

https://jp.heroku.com/
https://devcenter.heroku.com/articles/heroku-cli
アカウント作成とheroku-cliを導入

```
$ pwd
/var/www/html/src # dockerの中
$ php artisan --no-ansi key:generate --show  //APP_KEYとして後で使います
base64:xxxxxxxxxxxxxxxxx # (*1)
$ exit # dockerから出る
$ cd ../src # laravelのディレクトリへ
$ heroku login
$ heroku create {herokuのアプリ名}
$ heroku config:set APP_KEY=base64:×××××××××××××× # (*1)をAPP_KEYに使用
$ heroku buildpacks:add heroku/php # phpが動くように
$ heroku addons:create cleardb:ignite --app {herokuのアプリ名} # MySQLの有効化。メッセージに従ってクレジット情報の追加が必要です。
$ heroku config # DBの情報が表示されます
CLEARDB_DATABASE_URL: mysql://{ユーザ名}:{パスワード}@{ホスト名}/{DB名}?reconnect=true
```

herokuのDBを設定します。
laradockの /laravel/.env は　.gitignore でプッシュされないので、この設定がherokuでのDB環境の設定になります。

```
# 表示された情報を元にherokuのDBを設定。
$ heroku config:set DB_CONNECTION=mysql
$ heroku config:set DB_USERNAME={ユーザ名}
$ heroku config:set DB_PASSWORD={パスワード}
$ heroku config:set DB_HOST={ホスト名}
$ heroku config:set DB_DATABASE={データベース名}
```

## herokuでMySQLを使うための設定
ローカルではマイグレーションが出来るのですが、herokuではエラーが出ます。
直面していたエラー↓

```
~ $ php artisan migrate:fresh
Dropped all tables successfully.
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table

In Connection.php line 671:
                                                                                                                                 
  SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes (SQL: alter    
  table `users` add unique `users_email_unique`(`email`))                                                                        
                                                                                                                                 

In Connection.php line 464:

  SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes
```

2014_10_12_000000_create_users_table のマイグレーションでエラーが出ているので、そのファイルに下記の変更を。

```
- $table->string('email')->unique();
+ $table->string('email', 191)->unique();
```

あるいは　app\Providers\AppServiceProvider.php に以下を記述

```
use Illuminate\Support\Facades\Schema; // 追加

public function boot()
{
    Schema::defaultStringLength(191); // 追加
}
```

## Fakerを使う場合はpackage.json/package-lock.jsonを更新する

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

## Procfileを作ってプッシュ

```
$ pwd
laravel
$ echo "web: vendor/bin/heroku-php-apache2 public/" > Procfile
$ git add .
$ git commit -m "何かしらのメモ"
$ git push heroku master
```

プッシュ（＝デプロイ）するとherokuがphpファイルだと認識して、諸々のインストールを始めます。
ただ、VScodeではプッシュの最後に下記のエラーが発生。

```
remote:  !     Push failed: cannot parse Procfile.
remote:  !     Please try pushing again.
remote:  !     If the problem persists, see http://help.heroku.com/ and provide Request ID xxxxxxxxxxxxxxxxx. 
```

エラーメッセージのリンクから、Procfileで検索すると解決策を発見。
https://help.heroku.com/CH22EKEK/why-am-i-seeing-push-failed-can-not-parse-procfile-when-deploying-my-app

Procfileを「UTF-8」で保存。
VScodeだと右下の「UTF-16 LE」とあるものをクリックして、「save widh encoding」を選択し、「UTF-8」を選択。
再度コミット/プッシュで解決しました。

## heroku確認

```
$ pwd
laravel
$ heroku run php artisan migrate:fresh --seed
$ heroku open
```

http://{herokuのアプリ名}.herokuapp.com/
が開かれてホーム画面が出るはず。

## Xserverにデプロイする場合

### laravelを使えるようにするまで

https://qiita.com/n_oshiumi/items/2a1cc7d147ee1eff3e23
こちらの記事を参考に、PHPバージョンアップ、composerのインストール、npmを使えるように。

.bash_profileや.bashrcが出てくるのでその違いをチェック。
https://qiita.com/magicant/items/d3bb7ea1192e63fba850

### .htaccess

```
<IfModule mod_rewrite.c>

RewriteEngine On

RewriteRule ^(.*)$ public/$1 [L]

</IfModule>
```


### cron / タスクスケジュールを動かす場合

https://nebikatsu.com/6042.html/

### 手動でpublic/storageからstorage/app/publicへシンボリックリンクを張る方法

```
ln -s /home/{サーバーid}/{ドメイン}/public_html/storage/app/public /home/{サーバーid}/{ドメイン}/public_html/public/storage
```

※
右側: リンク元（ショートカットを新規作成）
左側: リンク先（既存のフォルダ）

.envの修正, サブドメインがあれば routes/web.phpのドメイン設定, .htaccessでpublicに向ける設定は必要。

### エラー: There is no existing directory at "/var/www/html/storage/logs" and it could not be created: Permission denied

sshなどでデプロイすると上記のエラーが出る。.envのDB設定が間違ってないかまずチェック。

/bootstrap/cache/config.php の記述のせい。

/bootstrapディレクトリについてはこちらのアーティクルにて記述がありました。
https://qiita.com/shosho/items/93cbff79376c41c3a30b#bootstrap

### エラー: where php_network_getaddresses: getaddrinfo failed: Name or service not known

ログイン認証時に、.envのDB_HOSTが合っているのにこれが出た。

```SELECT * FROM `users` WHERE `email` = xxxx.example.com;```

クエリはエラー。phpmyadminでＳＱＬを実行してもエラー。

```SELECT * FROM `users` WHERE `email` = 'xxxx.example.com';```

emailの値をクォーテーションで囲うと正常に処理される。

１）データベースがキャッシュされている可能性。

https://stackoverflow.com/questions/30182984/sqlstatehy000-2002-php-network-getaddresses-getaddrinfo-failed-name-or-ser

bootstrap/config.php を一旦外すと問題なく処理される。

２）collation設定の問題

https://qiita.com/toontoon/items/740b9575d2a323e93c0d#%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E3%81%B8%E3%81%AE%E6%8E%A5%E7%B6%9A%E5%AE%9A%E7%BE%A9%E3%82%92%E6%9B%B8%E3%81%8F

クオーテーションを付けると処理できたため。collation設定の問題の可能性。（調査中）