Home > アーカイブ > 2014-05

2014-05

Heroku で Composer を使う時に気を付けたいこと

この記事の所要時間: 745

Heroku が PHP をサポートしたので、テストがてら Laravel アプリケーションをデプロイしてみました。

heroku-logo-light

デプロイしたのは、Doctrine を利用するアプリケーションだったのですが、ローカルでは composer でインストールできるのですが、Heroku にデプロイするとインストールされないという現象が起こりました。

Laravel での Doctrine 使用

今回のアプリケーションでは、DBのテーブルスキーマ情報を読み込んで、動的に画面を作るという処理があり、そこで Doctrine の SchemaManager を使っていました。

Laravel で、Doctrine の SchemaManager のインスタンスを取得するのは簡単で、下記のメソッドを実行するだけです。

$manager = DB::connection()->getDoctrineSchemaManager();

こんなあっさりなので、laravel/frameworkパッケージをインストールすると、Doctrine も入るものだと思ってました。

Heroku での Composer

Heroku へデプロイするコードのルートディレクトリにcomposer.jsonが含まれていると、PHPアプリケショーンとしてセットアップが行われます。(依存解決に Composer を使わない場合でも、空のcomposer.jsonが必要です。)

このcomposer.jsonでは、通常の依存関係を指定するだけでなく、実行するPHPバージョンや拡張の指定ができます。例えば、下記のようにするとPHP 5.5.12をランタイムにして、memcached拡張が利用できます。

{
  "require": {
    "php": "5.5.12"
    "ext-memcached": "*",
  }
}

この記法は、Composer としてはサポートしているのですが、Composer 自身がランタイムの変更などを行うわけではありません。

そこで、Heroku の Composer は独自拡張しているのだろうと考えました。まあ、この思い込みが惑わすわけですが。

あと、Heroku での PHP サポートは、まだベータなので、そのせいもあるのかなと思ってました。

https://getcomposer.org/doc/02-libraries.md#platform-packages

開発環境、別 PaaS では正常に動作

もちろん開発環境(OSX, Linux VM)では、Heroku にデプロイしたものと同じコード(composer.(json|lock))で問題無く動いていました。

別のPaaSを試してみようと思い、Pagodabox に設置すると、これも正常に動作しました。

Heroku と 別 PaaS で、vendor/ 以下を比べると、10個近くのパッケージがHerokuでは入っていませんでした。

なぜ Heroku だけ入らない。やっぱり、独自拡張のせい?ベータ版だから?

–no-dev!

この作業していたのが、夜中でした。Pagodabox にデプロイできたので、これで良しとして、その日は寝ました。

しかし、気になるのが、同じ現象をググっても、Laravel アプリケショーンが Heroku で動かない,
Doctrine が入らないなんて出てこないんですね。動かしてみた系の記事はあるのに。

翌日、もう一度、Heroku の公式のドキュメントを読み直すことにしました。

すると、ありました。ちゃんと書いてありました。実行する composer コマンドが。

Heroku では、下記のオプション付きで実行するようです。そう、--no-devオプション付きでね!

$ composer install --no-dev --prefer-dist --optimize-autoloader --no-interaction

早速、手元で同じオプションで実行してみると、ちゃんとDoctrineがインストールされない。

ああ、これか。。。

Heroku PHP Support | Heroku Dev Center

–no-dev オプション

composer コマンドでは、いくつかオプションを指定することができ、--no-devはその一つです。

Composer公式サイトでは、下記の記述があります。--no-devオプションを付けると、依存解決する際にcomposer.jsonrequire-devセクションの内容は解決されません。

--no-dev: Skip installing packages listed in require-dev.

デフォルトでは、--devが付いているのと同じ状態になり、require-devセクションの内容も依存解決の対象となります。

https://getcomposer.org/doc/03-cli.md#install

依存パッケージのcomposer.jsonをチェック

アプリケーションが依存しているパッケージのcomposer.jsonを洗い出してみると、require-devにDoctrineを指定しているものはいくつかあれど、requireに指定しているものは見事にありませんでした。

つまり、開発環境やPagodaboxでは、--no-dev無しだったため、require-devセクションを含んで依存解決したため、Doctrine が入っていました。

かたや、Heroku では、--no-devありだったので、Doctrine が入りませんでした。おそらく Heroku だけに入らなかった他のパッケージも同様でしょう。

[解決] require に doctrine を指定

はい、原因は分かったので、解決方法です。

composer.jsonrequireに、Doctrine を追加しました。

    "require": {
        "php": ">=5.4.0",
        "laravel/framework": "4.1.*",
        "doctrine/dbal": "~2.3" // <--- 追加!
    },

Heroku にデプロイすると、バッチリ動きました!Herokuさん、疑ってゴメン。

実際にデプロイしたものが下記です。

http://laravel-table-admin.herokuapp.com/crud/classes

コードは、Github で公開しています。Heroku でも Pagodabox でもデプロイできているので、両 PaaS にPHPアプリケーションをデプロイする際は参考にどうぞ。

https://github.com/shin1x1/laravel-table-admin-example

さいごに

まあ分かってしまえば、単純というよくある話です。

Heroku が Composer を拡張しているかどうかは分かりませんが、ドキュメントには、composer 実行前に self-update しているという記述もあるので、Composer は標準のもので、別途compoer.jsonを見てランタイムを決定するシステムがあるのかもしれません。

あと、夜中に躓いたら、さっさと寝るということですね。睡眠大事。

追記

ラインタイムや拡張を実際に指定する処理は、PHP の buildpack に記述がありました。@iakio さん、ありがとうございました!

  • コメント (Close): 0
  • トラックバック (Close): 0

Home > アーカイブ > 2014-05

検索
フィード
メタ情報

Return to page top