🎻

symfony/monolog-bundleを入れているプロジェクトがプロダクション環境で動かなかった話

2020/04/10に公開

僕がSymfonyプロジェクトを作るときに毎回使っている ttskch/symfony-micro-skeleton というイカしたスケルトンがあるんですが、これを使って作ったプロジェクトをHerokuにデプロイしたら

PHP Fatal error:  Uncaught Error: Class 'Symfony\Component\Console\ConsoleEvents' not found in /path/to/vendor/symfony/monolog-bridge/Handler/ConsoleHandler.php:139

というエラーになってしまいました。原因と解決方法などをメモに残しておきます。

そもそもHerokuでSymfonyを動かすときの注意点

HerokuでPHPプロジェクトがビルドされる際に実行されるコマンドは

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

となっていて、 --no-dev が付いているので require-dev で依存しているライブラリはインストールされません。(公式情報

なので、Symfonyプロジェクトをホストする場合は、環境変数に APP_ENV=prod を明示的にセットしておかないと、 require-dev なクラスが色々とNot foundになってしまって動作しません。

symfony/monolog-bundleの罠?

今回起こったのは、

  1. symfony/monolog-bundleがインストールされていて
  2. Symfony Recipeによってインストールされた デフォルトの prod/monolog.yaml が配置されているプロジェクトを
  3. Herokuにデプロイして APP_ENV=prod をセットしたら
  4. PHP Fatal error: Uncaught Error: Class 'Symfony\Component\Console\ConsoleEvents' not found in /path/to/vendor/symfony/monolog-bridge/Handler/ConsoleHandler.php:139 になった

ということです。

コードを追ってみると、

  1. デフォルトの prod/monolog.yamlconsole ハンドラーが使われている
  2. そして、symfony/monolog-bridgeの ConsoleHandler クラスは、symfony/consoleの各種クラスに依存している
  3. しかし、symfony/monolog-bundleはsymfony/consoleに require-dev でしか依存していない
  4. なので、symfony/monolog-bundleをrequireしただけのアプリだと、 composer install --no-dev かつ APP_ENV=prod の環境においてsymfony/consoleの各種クラスがNot foundになってしまう

という状況のようでした🤔

デフォルトの prod/monolog.yamlconsole ハンドラーが使われていることが間違いな気がするので、とりあえずsymfony/recipesにissueを立ててみました。反応を待ちます。

https://github.com/symfony/recipes/issues/752

解決策

当たり前ですが、以下のように config/packages/prod/monolog.yamlconsole ハンドラーを使わないようにしておけばとりあえずエラーにはなりません。

# config/packages/prod/monolog.yaml

-         console:
-             type: console
-             process_psr_3_messages: false
-             channels: ["!event", "!doctrine"]
+ #        console:
+ #            type: console
+ #            process_psr_3_messages: false
+ #            channels: ["!event", "!doctrine"]

ttskch/symfony-micro-skeletonでもとりあえず同様の対処をしてあります。

本家のissueで何か別解が示されたらそれに合わせた対応をしようと思います。

まとめ

  • symfony/monolog-bundleをインストール&レシピでmonolog.yamlを作成したままだと、 composer install --no-dev かつ APP_ENV=prod な環境で以下のエラーになった
    • PHP Fatal error: Uncaught Error: Class 'Symfony\Component\Console\ConsoleEvents' not found in /path/to/vendor/symfony/monolog-bridge/Handler/ConsoleHandler.php:139
  • SymfonyアプリをHerokuでホストしている場合に起こりやすいのでお気をつけて
  • console ハンドラーを使わないように prod/monolog.yaml を修正すればとりあえず直る
  • https://github.com/symfony/recipes/issues/752 の反応を待つ
GitHubで編集を提案

Discussion