この記事は、CYBOZU SUMMER BLOG FES '26の記事です。
こんにちは、Garoon開発チームの松尾です。本記事では、PHPerKaigi 2026のセッション資料「PHPのバージョンアップ時にも役立ったAST(2026年版)」の内容をベースに、PHPのバージョンを8.4から8.5に更新する作業の一部でAST(抽象構文木、Abstract Syntax Treeの略)が役立つ場合があることを紹介します。
約2年前のCYBOZU SUMMER BLOG FES '24において「PHPのバージョンアップ時にも役立つAST(抽象構文木)」という記事を書きました。
その記事では、実際のプロダクト開発におけるPHPのバージョンアップ時にASTが役立つ場合があり、テスト範囲を絞る判断材料として使えるケースがあることを紹介しました。今回の記事では、その考え方をPHP 8.5へのバージョンアップ時にも適用できるケースがあることを紹介します。
セキュリティのためにもバージョンアップは必要
Garoon開発チームにはいくつかのサブチームがあり、私が所属しているサブチームであるYukimiチームは、より安全なGaroonをユーザーに届けることを目標とし、将来にわたって継続的にGaroonを安定提供できるように開発および保守を行っています。
PHPのバージョンアップは、アプリケーションを安全に運用し続けるために欠かせない作業です。PHPは年に1回新しいバージョンがリリースされます。リリースされてから不具合やセキュリティの問題が修正される「アクティブサポート」期間が2年間あり、さらにその後の2年間、重要なセキュリティ問題のみが修正される「セキュリティサポート」期間が設けられるようになっています。
PHPのサポート期間については、PHPの公式サイトを参照してください。
サポートが終了したバージョンを使い続けていると、脆弱性が見つかった場合でも当該脆弱性が修正されないままとなってしまいます。プロダクトを長期的に安全に運用するためには、PHP本体を継続的にアップデートしていく必要があります。
一方で、PHPのバージョンアップは簡単ではありません。PHPの新しいバージョンでは、新機能が追加されるだけでなく、下位互換性のない変更や将来的に削除される予定として非推奨になる機能が含まれることがあります。アプリケーション側では、それらの変更点を調査し、影響するコードを見つけ、修正し、テストする必要があります。コードベースが大きくなるほど、この作業は重い負担となります。
本記事で取り上げるASTは、ソースコードを構文として解析し、プログラムの構造を木構造で表したものです。空白や改行などの見た目の違いを気にせず、PHPの構文としてどのように解釈されるかを扱えます。ASTを知っていると、PHPバージョンアップ時の負担を軽減するのに役立つ場合があります。今回は、PHP 8.5で非推奨となる下記2つの例を取り上げます。
- 正規化されていない型名でのキャスト
switch文のcaseをセミコロンで終了させる書き方
PHP 8.5で非推奨となる機能については、PHP公式の移行ガイドでも説明されています。
見た目は変わるが、構文上の構造は変わらない
これら2つの変更に共通しているのは、ソースコード上の見た目は変わるものの、プログラムにおける構文上の構造としては変わらない、という点です。
例えば、(integer)を(int)に変更した場合、テキストとしては差分があります。しかし、どちらも「整数へのキャスト」を表す構文です。同様に、switch文のcaseをセミコロンで終了させる書き方をコロンに変更した場合も、ソースコード上の記号は変わりますが、caseラベルとしての構造は変わりません。
このような変更は、人間がコードレビューで確認すると「本当に挙動が変わっていないか」を判断する必要があります。また、変更箇所が多い場合には、すべての変更箇所に対して同じ粒度でテストを実施すると大きな工数がかかります。
そこで、ソースコード変更前のASTと変更後のASTを比較します。ここでいうASTの比較は、同じPHPパーサーを使って変更前後のコードを解析し、その結果を比較することを想定しています。ASTに差分がないことを確認できれば、少なくともPHPの構文として解釈した結果は変わっていないと判断できます。これにより、変更内容が表記上の修正に留まっていることをツールを使って確認でき、テスト範囲を絞る判断材料にできます。
正規化されていない型名でのキャスト
まず、正規化されていない型名でのキャストについて見ていきます。ここでいう「正規化されていない型名」とは、(integer)や(boolean)、(double)、(binary)のように、現在推奨される正規のキャスト表記とは異なるキャスト名のことです。
PHPでは、次のようなキャスト表記を書くことができます。
$value = (integer) $input; $flag = (boolean) $enabled; $rate = (double) $number; $data = (binary) $value;
これらは、それぞれ次のような正規化された表記に置き換えられます。
$value = (int) $input; $flag = (bool) $enabled; $rate = (float) $number; $data = (string) $value;
ソースコード上は、(integer)が(int)に、(boolean)が(bool)に、(double)が(float)に、(binary)が(string)に変わっています。そのため、通常のテキスト差分では当然ながら変更として表示されます。
しかし、PHPの構文として見た場合、どちらも同じキャストを表しています。(integer)と(int)はどちらも整数へのキャストであり、(boolean)と(bool)はどちらも真偽値へのキャストです。同様に、(double)と(float)、(binary)と(string)もそれぞれ同じキャストを表します。
このような変更では、ソースコードの表記は変わっていても、ASTとしては同じ構造になることが期待できます。実際にphp-astを使って確認してみたところ、対象となるキャスト表記を正規化したうえで変更前後のASTを比較し、ASTに差分が出ないことを確認できました。
このことから、変更内容が「キャスト表記の正規化」に限られており、式の構造自体は変わっていないことが分かります。
switch文のcaseをセミコロンで終了させる書き方
次に、switch文のcaseをセミコロンで終了させる書き方について見ていきます。
PHPでは、次のようにcaseの後ろにセミコロンを書くことができます。
switch ($type) {
case 'admin';
return true;
case 'user';
return false;
}
多くの場合、次のようにコロンを書くと思います。
switch ($type) {
case 'admin':
return true;
case 'user':
return false;
}
この変更も、テキストとしては;が:に変わるため差分があります。しかし、構文上はどちらも switch文のcaseラベルを表しています。
こちらも、バージョンアップ前のPHP 8.4環境でphp-astを使って確認してみたところ、セミコロンをコロンに置き換えてもASTは同じであり、switch文の分岐構造そのものは変わっていないことを確認できました。
このような変更は、見た目の差分だけを見ると大量の修正に見えることがあります。しかし、ASTとして差分がないことを確認できれば、変更の性質をより正確に把握できます。
ASTに差分がないことを確認してテスト方針を決める
ここまで見た2つの例は、どちらもPHP 8.5へのバージョンアップに伴って修正が必要になる可能性があるものです。一方で、修正内容はプログラムの構造を変えるものではなく、表記を新しいバージョンに合わせるための変更です。
もちろん、ASTに差分がないからといって、あらゆる観点で安全であると断言できるわけではありません。ASTはソースコードの構文構造を表すものであり、実行時の値、外部環境、設定、テストデータの違いまでは表しません。
しかし、今回のように「表記は変わるが構文上の構造は変わらない」ことを確認したい場合には、ASTの比較は強力な判断材料になります。
変更前後でASTに差分がないことを確認できれば、少なくともPHPのパーサーが解釈する構文構造は変わっていないと判断できます。これにより、変更箇所ごとに人間が確認する負担を減らしたり、テスト範囲を必要以上に広げずに済ませたりできる場合があります。
PHPのバージョンアップ対応では、修正対象が多くなりがちです。すべての変更を同じ重さで扱うと、確認作業のコストが大きくなります。ASTを使うことで、機械的に安全性を確認しやすい変更と、人間が重点的に確認すべき変更を分けやすくなります。
まとめ
実際のプロダクト開発におけるPHPのバージョンアップでは、ASTがテスト範囲を絞る判断材料として役立つ場合があります。今回の記事では、その考え方をPHP 8.5へのバージョンアップ時にも適用できるケースがあることを紹介しました。
PHPをバージョンアップする際には、多くの変更点の調査やテストが必要になります。しかし、ソースコード上の見た目は変わっていても、ASTが変化せず、構文上の構造としては同等とみなせる変更もあります。PHPのバージョンアップ時にそのような変更を見分けることで、テスト範囲を絞る判断材料にできる場合があります。
本記事の内容については、PHPerKaigi 2026のセッション資料もあわせて参照していただくと、より理解が深まると思います。php-astのutil.phpを使ってASTを取得および比較する方法を紹介していますので、よろしければ当該資料もご参照ください。