🫨

PHP7.1 Laravel5系をバージョンアップした話 〜準備が全てだった〜

2024/10/04に公開

はじめに

こんにちは、助太刀バックエンドチームの水本です!

今回は、弊社が運用しているサービスの PHP および Laravel のバージョンアップに取り組んだ際の体験談を共有したいと思います。
全3部作でお届けする予定ですが、できる限りわかりやすくまとめていきますので、ぜひお付き合いください!

まず最初のこの記事では、バージョンアップにおける「準備」がいかに重要だったかという点についてお話しします。

バージョンアップの意義

バージョンアップは、セキュリティの強化やパフォーマンスの向上、新機能の追加など、長期的な運用を考える上で欠かせないものです。
PHPに限らず、開発環境の進化に対応していくことで、より効率的で安全なサービス提供が可能になります。

具体的にPHPのバージョンアップによりどんな利点があるか記載します。

  • セキュリティ強化
    古いバージョンでは、既知の脆弱性が修正されていないケースがあるため、バージョンアップすることでそれらが改善され、外部からの攻撃リスクが軽減されます。

  • パフォーマンスの向上
    特にPHP8.0以降、JIT(Just In Time)コンパイルが導入され、処理速度向上が期待できます。
    これにより、負荷が高い状態でも応答速度が改善できる可能性があります。

  • 新機能の活用
    PHP8.0では型システムの強化や、Enumなどのモダンなプログラム言語機能が導入されました。
    これにより、コード品質向上やバグの早期発見が可能となり、保守性が高まります。
    特に、型の厳密性が高まったことでバグの予防に大きく貢献し、私個人としてもぜひ導入したかった理由になります。

  • 新しいComposerパッケージの利用
    バージョンアップすることで、最新のComposerパッケージが利用可能になったりします。
    例えば、 OpenAI API を利用するための公式・非公式パッケージが8.0以降のバージョンのみで提供されているため、車輪の再発明をすることなく、容易に活用できるようになります。

これらの利点により、私たちはバージョンアップをするという決断をしましたが、そのためには事前の「準備」が非常に重要でした。

なにより重要なのは「テスト」でした

バージョンアップ作業において、最も重要であり助けられた部分は「テストコード」の存在でした。今回はPHP7.1からPHP8.2Laravel5.xから9.xへバージョンアップを行いましたが、一気に大きなバージョンアップを行わず、段階を踏んで慎重に進める方法を採用しました。これによりできるだけリスクを最小限に抑えつつ移行することができました。

テストコードが防いでくれたデグレ

今回のバージョンアップでは、テストコードがプロジェクト全体の「安全ネット」として機能してくれました。段階的に進めたとはいえ、破壊的変更のリスクがゼロになるわけではありません。そこで、テストコードとGitHub Actionsを使用し、確実に動作が保たれていることを確認しました。

  • 破壊的変更の検出
    マイナーバージョンのアップグレードでも同様ですが、特にPHP8系の言語仕様やメソッドの挙動に変更が入っており、特定の処理の互換性を失うケースが発生しました。それをテストコードによって事前に検出し、デグレを防ぐことができました。(ただし、PHPUnit自体のメソッドの振る舞いが変わることもあり、苦労する場面もありました🫠)

  • リファクタリング後の動作確認
    後述に記載しますが、PHP-CS-Fixerrectorを使用して、バージョンアップ後にリファクタ等のコード変更を行っていました。その際もテストコードによって正しい動作が保証することができました。

テストのカバレッジの重要性

バージョンアップ作業において、テストコードが存在するだけでなく、それがどの範囲までコードを網羅しているか、つまりテストのカバレッジが非常に重要な役割を果たしました。カバレッジを計測することで、どのコードがテストされているか定量的に把握し、リスクのある部分を明確にすることができたと思います。

他のバージョンアップに役立ったツール等の紹介

バージョンアップ作業を円滑に進めるために、いくつかのツールを活用・導入しました。これらのツールは、テストやコードの品質を保ちつつ、作業の効率化を助けてくれました。以下に特に役立ったツールを紹介します。

PHPStan + Larastan

これらは、PHP、Laravelの静的解析ツールとして非常に有用でした。コードを実行せずに型や構造上のエラーを事前に検出してくれるため、バージョンアップ時にも重大な不具合を未然に防ぐことができました。自動テストの際にも、動的で曖昧だった部分が型付けされたことにより、想定外の動きをするというコードの誤りを検知し、問題の早期発見に貢献してくれました。

PHP-CS-Fixer

PHP-CS-Fixerは、コードフォーマットを自動的に整えるツールです。このツールを活用することで、チーム全員が一貫した書き方を維持でき、差分が激減しました。結果として、レビューの際に注目すべきは本質的な部分のみに集中することができ、バージョンアップ前後のコードレビューにかかる負担を大幅に軽減することができました。

また、通常の開発においても欠かせない存在で、コードの可読性や、メンテナンス性を向上させてくれました。

しかし、導入当初はフォーマットによるコード差分が約+29,250 −16,409行も発生し、その大きさに驚きました。これだけ大規模な変更に対して不安もありましたが、テストコードが整備されていたおかげで、安心して一気に導入することができました。

Rector

Rectorは、PHP や Laravel のバージョンアップにおいて欠かせないツールです。Rector はコードを自動でリファクタリングし、最新バージョンに適合させるための修正を提案してくれます。特に大きなバージョンアップにおいては、これまでの書き方を新しい方法に適応させる必要があるため、Rectorの自動リファクタリングが大いに役立ちました。

Rectorは、推奨されなくなったメソッド廃止されたメソッドも自動で検出し、修正を提案してくれる機能を備えています。特にPHP8系に上げるときは、多くの非推奨機能が追加されたり、Laravelでも破壊的変更がいくつか存在しました。Rectorはこれらの部分を自動で提案、修正してくれるため、バージョンアップ作業におけるリファクタの大きな手助けとなりました。

ただし、全ての提案をそのまま適応できるわけではないので、必要に応じてルールの除外等を選択しましたが、最新のベストプラクティスに移行するためのガイドとしても非常に役立ちました。

これらのツールは、バージョンアップ作業の成功を支える重要な存在でした。それぞれのツールが、コードの品質や作業の効率化に貢献し、段階的にバージョンアップを進める際に大きな助けとなりました。これからバージョンアップを検討している開発者だけでなく、機能を追加していく開発者にも是非使っていただきたいツールです。

まとめ

今回のバージョンアップを通じて、準備の重要性を改めて実感しました。特に、テストコードの整備や静的解析ツールの導入は、想定外のデグレや不具合を未然に防ぐ上で欠かせない要素でした。これらの取り組みによって、大規模なバージョンアップでもリスクを最小限に抑え、安全かつ効率的に進めることができたと思っています。

また、新しいバージョンのPHPやLaravelに移行することで、セキュリティの強化やパフォーマンスの向上、新機能の活用といった多くのメリットを享受できるようになりました。特に型の厳密性や新しい言語機能は、コード品質向上に大きく寄与し、開発する上でのモチベーションの向上にも繋がっています。

バージョンアップは一見ハードルが高く感じられますが、適切な準備とツールの活用、そして段階的な移行を行うことによってその困難さを大幅に軽減できます。この記事が同じようにバージョンアップを検討している方々の一助になれれば幸いです。

次回の記事では、実際にバージョンアップの際に踏んだトラップや、その解決方法について詳しくご紹介しますので、ぜひご覧ください。

今後も技術の進化に適応し、より良いサービスを提供できるよう、引き続き取り組んでいきたいと思います。最後までお読みいただき、ありがとうございました!

助太刀について

助太刀では一緒に開発してくれるメンバを募集してます!
少しでもご興味を持っていただけたら下記よりお気軽にご連絡ください!

GitHubで編集を提案
助太刀テックブログ

Discussion