🦾

PHP 7.3 → 8.0 | Laravel 5.8 → 8.0 のアップグレードをした話

2021/10/10に公開

はじめに

受託開発のWEBアプリで使用していた PHP 7.3 のセキュリティサポートが 2021/12/06 に切れてしまうため、
委託元にお願いしてバージョンアップを行うこととなりました。

またずっと使い続けていた Laravel 5.8 も、とっくの前にセキュリティサポートが切れていたので、
合わせて一緒にアップグレードすることになりました。

注意

  1. PHP のバージョンアップに伴う修正は結果的にほぼなかったので、 Laravel のアップグレードの話がメインになります。
    1. フロント側は Vue.js で作っているため、サーバサイドの対応のみです。
  2. 私ひとりでやったわけではなく、5〜6人ほどのチームで行ってます。

バージョンアップ前の環境

  • PHP 7.3
  • Laravel 5.8
  • composer 1.x

※以降は上記を「旧環境」と表記します。

バージョンアップ後の環境

  • PHP 8.0
  • Laravel 8.x
  • composer 2.x

※以降は上記を「新環境」と表記します。

下準備

開発環境構築

ローカルの開発環境で旧環境を壊したくなかったので、ローカルの別の場所にリポジトリを pull してきてバージョンアップの環境を構築しました。
新環境は Laravel Sail を使って構築することにしました。
https://readouble.com/laravel/8.x/ja/sail.html

ブランチ構成

紆余曲折あり、最終的に以下のようなブランチ構成で進めることになりました。
ブランチ名は一部略記しています。

ブランチ名 作成元(マージ先) 説明
dev 開発ブランチ
pre-update dev ヘルパ関数や名前空間の修正
update-laravel pre-updatedev パッケージのアップグレードとそれに伴う修正
update-factory update-laravel ファクトリの修正
update-passport update-factory 認証機能の修正
update-test update-passport テストの修正
ややこしいですが、修正したブランチからさらにブランチを生やして、バケツリレーみたいにしてるイメージです。
あとこれも後で後悔したのですが、update-factoryupdate-passport は逆の方が良かったです。

アップグレード作業

ヘルパ関数や名前空間の修正

作業ブランチ: pre-update
旧環境の状態で事前にできる修正を行い、先にマージすることにしました。

  • 6.x からヘルパ関数が本体から削除されパッケージ化されるため、導入して修正
  • 名前空間とファイル名が異なっているファイルの修正
  • その他、細かな typo の修正

Laravel 本体のアップグレードとアップグレードガイドに沿った修正

作業ブランチ: update-laravel
アップグレードガイドを読みながらバージョンを1つずつ上げていき、該当する箇所を修正しました。
このブランチで対応したのは主に以下の箇所です。

  • 【6.x】 policy に viewAny() メソッドを追加
  • 【6.x】 FormRequest の validationData() メソッドを public に変更
  • 【7.x】 Symfony5 へのアップグレードに対応
  • 【7.x】 Eloquentモデルで serializeDate() メソッドをオーバーライド
  • 【8.x】 シーダとファクトリへ名前空間を追加
  • 【8.x】 failed_jobs テーブルに uuid 列を追加し、既存のデータに uuid を流し込み

あと細かな点でいえば、以下の点も修正しました。

  • config を Laravel 8.0 基準にし、 .env のパラメータ名を一部変更
変更前パラメータ名 変更後パラメータ名
MAIL_DRIVER MAIL_MAILER
QUEUE_DRIVER QUEUE_CONNECTION

factory の修正

作業ブランチ: update-factory
ファクトリが新しい記述方式になり、Laravel 8.x で従来のファクトリを使用する場合は laravel/legacy-factories パッケージを入れる必要がありました。
今回はこのパッケージを入れず、全てのファクトリを修正し、ファクトリを呼び出す部分も修正しました。
ファクトリの修正は地道に手作業でやりました。
呼び出す部分に関しては、エディタ(VScode)の置換機能を利用して大まかに修正し、あとは手作業で修正しました。

// 単体
検索 >> factory\((.+)::class\)
置換 >> $1::factory()
// 複数モデル作成
検索 >> factory\((.+)::class, (.+)\)  
置換 >> $1::factory()->count($2)

ここが作業量としては一番多かったです。

認証機能の修正

作業ブランチ: update-passport
複数の認証プロバイダを使用していたため、旧環境では smartins/passport-multiauth を使用していました。
しかし本家の laravel/passport が複数プロバイダに対応したことと、 PHP 8.x では smartins/passport-multiauth が非推奨となっていたため、乗り換えることにしました。
laravel/passport の導入は公式ドキュメントに沿って行い、passport-multiauth を使用していた部分を対応する記述へ書き換えるだけで認証ができたので、乗り換え自体は想像していたより容易でした。
ただ一番影響が大きそうな部分でもあったので、動作確認を念入りに行いました。
後述しますが、本番反映の際も認証テーブルの再作成や migrations テーブルの書き換えなどが必要だったので、事前に手順を洗い出すなど準備を怠らないようにしました。

テストの修正

作業ブランチ: update-test
今回 phpunitcarbon などのパッケージもアップグレードしたため、それによってテストが失敗している部分がありましたので修正を行いました。
修正の際は、アプリ本体に影響があるのかを確認しながら行いました。

  • 非推奨となった phpunit のアサーションの修正(assertRegExp() など)
  • carbon のバグ修正によるテスト失敗の修正対応(チームのメンバーが調べてくれました)

アップデートの影響でテストが失敗している部分の修正が終わったあとは、それ以外でテストが失敗している箇所を参考に、アプリ本体の修正を行いました。
一部APIレスポンスのステータスコードが変わっていたり、細かな仕様が変わっていたりで、テストがないと気付かない部分もありました。
あとテストがあると安心感が違いますね、心強かったです。

いざリリース

委託元とスケジュールを合わせ、リリース日を決めました。
リリースまでに開発環境やステージング環境で動作確認をできるだけ行いました。
そしてリリース当日は以下の作業を行いました。

  • メンテナンスモードへの移行
  • サーバの PHP のアップグレード
  • 新環境のデプロイ
  • 前述の認証テーブルの再作成とマイグレーションの実行
  • failed_jobs テーブルへの uuid 追加対応
  • supervisor のリスタート
  • 動作確認
  • メンテナンスモードの解除

特に大きなエラーもなく、無事にリリースをすることができました 🎉

さいごに

無事にリリースでき、達成感もありましたがホッとしたというのが率直な感想です。
やはりテストを書いていた恩恵が大きかったです。今後もテストを書き続けようと思いました。

せっかくアップグレードしたので、PHP 7.4 から使用できるようになったアロー関数や、 PHP 8.0 で取り入れられた match 式など、新しい機能をどんどん使用していきたいです。
型が書ける部分も充実させていきたいですね。
もちろん Laravel の新しい機能も取り入れていきたいです。
コード規約も見直ししたい...やりたいことがたくさんあります。

反省点も多いので、今後に活かしていきたいと思います。
大変だったけれどやって良かったです。
今後の開発が楽しみです。

Discussion