30分で出来ちゃう！？ Laravel AppをHerokuでお手軽に公開しよう！

# ご覧いただきありがとうございます！
Laravel Advent Calenderの10日目を担当する@neronplexと申します。なにぶん技術系の文章を書くのは慣れておらず、なおかつLaravel歴数ヶ月の初心者ではありますが、なにとぞお手柔らかにお願いします。

このAdvent Calenderも区切りのいい10日目となり、「ちょっとLaravelでなにか作ってみようかな」と思った方も多いはず（多いといいな。ちょうど東京ではヒカリエで勉強会もあったことですし）。そこで今回は、Laravelで作成したWebアプリケーションを、Herokuへデプロイして一通り動作させる方法をまとめてみたいと思います。ちなみに当方は初めてやろうとしたら半日くらい難儀して禿げ上がりそうになりました。

なお。今回はPHPの処理系としてHHVMを使っていくことを前提としてこの記事を書いていきたいと思います。


## では早速やってみよう！
HerokuへデプロイしたアプリケーションをPHPとして動作させるためには、「このアプリはPHPで組んだものだ」と教えてやる必要があります。これから、Laravelのディレクトリでいくつかのファイルを編集してもらう必要があります。そのあとは、いつも通り`git push heroku master`でOKです。

### composer.json
Herokuは、composer.jsonの有無で、PHPアプリケーションかどうかを判定します。composer.jsonはすでにパッケージの導入などで使っておりますが、これは特に編集することなくデプロイすればOKです。PHPの最新版で動作します。ただし、やんごとなき理由で特定のバージョンを使いたい場合は、composer.jsonで動作させるバージョンを指定することが出来ます。現在は**5.5系と5.6系のみサポート**されています。それ以前のバージョンで書かれているコードは、最低でも5.5系を基準としたコードへ改修する必要があります。

また、HerokuはHHVMも暫定的にサポートされており、composer.jsonで宣言することによって、HHVMで動作させることも出来ます。自分で環境構築するよりもお手軽でいいですね。こちらも、動作バージョンを指定することが出来ます。なお、コミット時にscriptsに書いてあるコマンドラインが実行されますが、そちらもHHVMで実行されるようにphpからhhvmへ書き換えましょう。phpのままだとコミット時にエラーで弾かれます。

```json:composer.json
/* 特定のバージョンを動作させる場合 */
{
	...
	"require": {
		"php": "~5.5.18",
		"laravel/framework": "4.2.*"
	},
	...
}

/* HHVMで動作させる場合 */
{
	...
	"require": {
		"hhvm": "*",
		"laravel/framework": "4.2.*"
	},
	...
}
```

### Procfile
Procfileでは、Heroku上で動作させるプロセスの宣言を行います。1行書けばいいだけなので、特に難しいことはありません。以下は、PHP / Apacheで動作させる場合の記入例です。publicはサーバーのドキュメントルートを指定しています。HHVMで動作させる場合はphpをhhvmへ、nginxで動作させる場合はapache2をnginxに書き換えれば、よしなに動きます（nginxは別途リダイレクトを処理するように設定ファイルを用意しないといけない）。

```text:Procfile
                        ↓ HHVMで動作させる場合はhhvm
web: vendor/bin/heroku-php-apache2 public/
                              ↑ nginxで動作させる場合はnginx
```

### .gitignore
HerokuにPHPをデプロイする場合は、composerを使った際に作成される、**composer.lockも一緒にデプロイする**必要があります。特になにもいじってないデフォルトの.gitignoreには、composer.lockをコミットしないよう宣言されているため、その行を削除する必要があります。


## HHVMを使う場合の注意点
先ほど、composer.jsonでHHVMを指定することが出来ると書きました。手軽に使えるのはいいのですが、HHVMを処理系として使う場合、注意しなければいけないことがあります。Heroku上で動いているPHPは、標準で動いているエクステンションが決まっていて、追加で使いたいエクステンションがある場合は、動作バージョンの指定と同じく、composer.jsonにて使いたいエクステンションを宣言することになります。`ext-`を接頭辞としてエクステンションの名前に付けます。

```json:composer.json
{
	"require": {
		"ext-memcached": "*"
	},
}
```

### HHVMはエクステンションをいじれない！
PHPはエクステンションを自由に追加することが出来ると上では書きました。しかし、HHVMではスタンダードセットなるもののみが有効になっており、**ユーザー側によるエクステンションの追加は現時点ではサポートされていません**。ですが、最低限Laravelを動作させる分にはちゃんと必要なエクステンションが有効になっているため、そこに関しては問題ありません。

ただし、エクステンションの追加が出来ないため、身近な問題としては**使えるRDBMSの種類が限定されます**（後述）。

なお、今回は[Heroku上にあるHHVMの動作環境を調べるためのモック](http://hhvminfo.herokuapp.com)（[HHVMinfo](https://gist.github.com/ck-on/67ca91f0310a695ceb65)を展開したもの）をご用意しました。ここを見ると、どういうエクステンションが使えるのかなど、大まかな動作環境を把握することが出来ます。デプロイを行う前などに参照するといいと思います。

### MySQLとSQLiteしか使えない
HerokuではPostgreSQLが標準でサポートされています。よって、自分も最初はPostgreSQLのアドオンを有効化すればスムーズに使えるようになると思っていました。そう、あの時までは。

それでは、先ほどのモックから[エクステンションのページ](http://hhvminfo.herokuapp.com/?EXTENSIONS)を開いてみましょう。Laravelでは、データベースとの通信にPDOドライバーを用いて接続します。よって、使いたいRDBMSのPDOドライバーが入っている必要があります。しかし、投稿時点で使えるエクステンションを確認してみると、pdo_mysqlとpdo_sqliteのみ有効になっていることが分かります。HHVMを使っている場合、自分でエクステンションを追加出来ないのは前述の通りです。よって、**Heroku上のHHVMでは、MySQLとSQLiteしかRDBMSを選択出来ない**ことになります。

これを知っていると、私のようにデプロイ後「DBが使えない！なんでや！！」とあたふたすることがなくなります。今後は使えるRDBMSも増えていくと思いますが、時間を無駄にしないためにも頭に入れておきましょう。


## マイグレーションを実行する
DBの接続先を設定してデプロイを行ったあとは、シェルでマイグレーションを実行すれば動くようになります。データベースのスキーマをマイグレーションで管理していない方は読み飛ばしても構いません。

### PHPならそこまでつまずかない
まず、マイグレーションを実行するために、Heroku上のbashを呼び出す必要があります。Herokuへデプロイするためのgitが置かれているディレクトリで`heroku run bash`を実行します。すると、じきにシェルが立ち上がります。ここで`php [or] hhvm artisan migrate`を実行します。これで、artisanが自動的にデータベースの設定を行ってくれます。

### HHVMは若干厄介
~~HHVMの場合は`hhvm artisan migrate --force`を実行します。ここで注意すべき点は`--force`オプションを付けていることです。現時点で**Heroku上のbashはinputStreamを受け付けてくれない**ため、普通に`hhvm artisan migrate`で実行してしまうと、yes/noの選択肢部分でエラーとなってしまいます。やっても特に不都合はありませんので、普通に強制実行してしまいましょう。~~

HHVMを使っている方で上記のinputStreamエラーが出る場合、Heroku上のスタックバージョンが低い可能性が高いです。HHVMの過去のバージョンで、**[名前空間を使っていると標準ストリームを受け付けないバグ](https://github.com/facebook/hhvm/issues/2544)**が存在しました。そのため、名前空間を多用しているLaravelは、このバグの影響を多分に受けてしまいます。このバグはすでに修正されており、特にHHVMの動作バージョンを指定していない方でこの問題が発生している場合は、スタックバージョンが低いため、すでに修正されたHHVMの最新版が使用出来る状態になっていないものと思われます。

### スタックバージョンを上げよう
執筆時点の最新版スタックであるCedar-14でデプロイすることの出来る"HHVM3.3.1"ではこの問題が解決していることを確認しています。これからHeroku上にアプリを作成する場合は問題ないと思いますが、すでにアプリを作成している人は、ダッシュボードにある各アプリのページから、"Production Check"をクリックしてみましょう。黄色い文字で"Cedar-14 stack"と表示されている場合、バージョンアップが推奨される環境です。

バージョンアップを行う場合、`heroku stack:set cedar-14`を実行すると、次回のデプロイから最新のスタックが有効になります。このあとデプロイしてからbashを呼び出してマイグレーションを実行すると、特にエラーが出ることなく実行出来ると思います。


## 最後に
いかがだったでしょうか。流石に「30分」は煽りすぎのような気もしますが、自分が当初つまずいた部分を余すところなく書いてみました。ご存じの通り、Herokuは無料でサクッと公開出来るという優秀すぎるPaaSとして有名です。是非、Advent CalenderでLaravelに興味を持たれた方は、サクッと書いてサクッと公開してみてください。あっ、デプロイがうまくいかなくてそのままぶん投げそうになってしまった私のような方々も是非是非。

明日の担当は@kento6453さんです。よろしくお願いします！

# 参考文献
* [Heroku PHP Support](https://devcenter.heroku.com/articles/php-support)
* [Migrating to the Celadon Cedar-14 Stack](https://devcenter.heroku.com/articles/cedar-14-migration)