#あすみかんの上にあすみかん

#たのしいことしかかかないことをここに決意します

Composerを2系にしたら、FuelPHPから「Call to undefined method Error::shutdown_handler()」といわれた

今日はバージョンアップ作業をしていときにFuelPHPPHPフレームワーク)から「Call to undefined method Error::shutdown_handler()」といわれた昔話をします。

この話はかなり脚色が入っています。 また、現在は当時の環境と全く異なっているため、昔書いたあすみめも(怪文)と睨めっこしながら思い出補正で記事を書いています。 空虚に向かって話す昔話として見てもらえると(っ'-')╮=͟͟͞͞🌹

前提&当時のゴール

N年前(0<N<100)、あるWebアプリケーションのアップデートが必要になりPJにアサインされました。 やらなきゃいけないことは山積みで、思い出せるだけでも以下がありました。

  • 外部APIのバージョンアップ
  • オンプレ環境からクラウド環境にのせる
  • PHPのバージョンアップ(5.x -> 当時の最新)
  • PHPフレームワークのバージョンアップデート/リプレイス

この環境はFuelPHPを使っており、バージョンも最新ではありませんでした。 技術スタックとしてFuelPHPを使い続けるかは議論の余地がありましたが、どうするかを決める優先度は低かったです。 (他があまりにも優先度高すぎるので...)

起きた問題

わたしがアサインされたのは「オンプレ環境からクラウド環境にのせる」ところです。 当時、確かコンテナにも載っていなかったので、その作業から始めたような気がします。

そして、もちろん(?)Composerも1系だったので、コンテナ化するときについでにComposerを2系していい感じにしちゃお、と考えました。 マルチステージビルドを利用して、以下のような感じでDockerfileを書きました。 ノリを伝えたいだけなので、めっちゃ適当に書いています。

# composer installをする
FROM composer:2.x as vendor

RUN composer install 

# Webアプリケーションを構築する
FROM php:apache-buster

COPY --from=vendor /app/vendor/ /app/vendor

また、composer.jsonは以下のようにpost-install-cmdを指定していました。 これはFuelPHPフレームワーク側で最初から書いてあるものです。

{
  "scripts": {
    "post-install-cmd": [
      "php oil r install"
    ]
  }
}

いざ、尋常に勝負!!ビルド!!!

PHP Fatal error:  Uncaught Error: Call to undefined method Error::shutdown_handler() in /.../fuel/core/bootstrap.php:77
Stack trace:
#0 [internal function]: {closure}()
#1 {main}
  thrown in /.../fuel/core/bootstrap.php on line 77

・・・落ちる!!! どうやらphp oil r installで落ちているようでした。

エラーの内容でピンとくる人いますか・・・? 正統派PHPer(?)はこれを見ただけで「はぁ〜ん」ってなるんですかね。 ちなみに当時の私はマジで本当に何もわからず、めちゃくちゃ時間を使っていた覚えがありますw

なぜ起きたか

www.php.net

PHPは7系以上からErrorクラスができました。 class ErrorPHPのすべての内部エラーの規定クラスとして定義されています。

github.com

そして、当時のFuelPHPのバージョンではclass Errorが定義されています。

そうです!!Errorクラスが衝突していたのです!!💥

bootstrap.phpFuelPHPのErrorクラスを参照したいが、コンテナ(実行環境)のPHPのバージョンを7以上としていたため、PHPの方のErrorクラスを参照してしまっているようでした。

解決方法

DockerfileのComposerバージョンを低く指定する

blog.packagist.com

As I mentioned above, Composer 2.0 supports PHP 5.3+,

Composer2.0などでは、古いPHPのバージョンをサポートしているので、Dockerfileでこのバージョンを採用すればComposerの2系を採用することができます。

当時は解決法として正しかったかもしれませんが、現在この方法はまったくもって推奨されません。 このComposerのバージョンは脆弱性が見つかっているためです。

jvndb.jvn.jp

Composerのバージョン上げを後回しする

その時自分がもっていたタスクは「クラウドにのせること」だったため、当時は後回しにしました。 後回しというか、「Composerを1から2にする」というタスクを自然な位置に持っていきました。

そもそもPHPが5系なのも既にやるべき課題としてありました。 FuelPHPPHPのバージョンアップと同時にComposerを2の最新まで上げることで自然に回避しました。

おわりに

息をするようにバージョンアップができる人間になりたい、ならなくちゃ、なるぞ