Slide 1

Slide 1 text

PHPのバージョンアップ時にも 役立ったAST 2025年2月22日 PHPカンファレンス名古屋2025 サイボウズ株式会社 松尾篤 1

Slide 2

Slide 2 text

PHPのバージョンアップ時にも役立ったAST トークの概要 はじめに • 勉強会で学んだことが実際の業務に役立った事例を紹介 • AST(抽象構文木、Abstract Syntax Treeの略)がPHP 8.1からPHP 8.2に バージョンアップした際の作業の一部で役立った事例 • ASTのハッシュ値に差分がないことを確認することで大幅にテスト工数を削減 2

Slide 3

Slide 3 text

PHPのバージョンアップ時にも役立ったAST 今回の話題 はじめに • PHPのリリースサイクルとバージョンアップの必要性 • PHPのバージョンアップ時に参照する移行ガイド • バージョンアップ時に挙動が変わらない根拠としてASTに着目 • PHPでASTを取得およびそのハッシュ値を比較する方法 • ASTのハッシュ値を確認する際に留意する点 3

Slide 4

Slide 4 text

PHPのバージョンアップ時にも役立ったAST 自己紹介 はじめに 松尾篤 • PHP使用歴:約20年 • PHPを使った開発歴は約17年 • 2023年4月にGaroon開発チームに加入 • Garoonのセキュリティを維持するYukimiチームの紹介 https://blog.cybozu.io/entry/2023/10/04/101916 • 過去にコントリビュートしたことがあるOSS(抜粋) • PHP Debug Bar • Smarty • Goss • mod_python • Serverspec 4

Slide 5

Slide 5 text

PHPのリリースサイクルと バージョンアップの必要性 5

Slide 6

Slide 6 text

PHPのバージョンアップ時にも役立ったAST PHPのリリースサイクル PHPのリリースサイクルとバージョンアップの必要性 • 年に1回新しいバージョンが公開 • 2年間のアクティブサポート期間 • リリースされてから不具合やセキュリティの問題が修正される • アクティブサポート期間の後に2年間のセキュリティサポート期間 • 重要なセキュリティ問題のみが修正される 6

Slide 7

Slide 7 text

PHPのバージョンアップ時にも役立ったAST もしもバージョンアップを行わなかったら PHPのリリースサイクルとバージョンアップの必要性 • PHPのセキュリティサポート期間の終了を迎えることになる • PHPに起因する不具合やセキュリティ脆弱性に対応できなくなる • 深刻なセキュリティ脆弱性がPHPに見つかって製品に重大な影響を与えて しまうような問題が出てきた場合にユーザーが危険な状況に陥ってしまう • サービスやビジネスの継続に影響を与えてしまう恐れも 7

Slide 8

Slide 8 text

PHPのバージョンアップ時にも役立ったAST セキュリティのためにもバージョンアップは必要 PHPのリリースサイクルとバージョンアップの必要性 • セキュリティに対するリスクマネジメントは重要な経営課題の1つ • 最新のセキュリティ更新をすぐに取り込める状態を保つことはとても重要 • 日頃から製品で使用しているソフトウェアやライブラリを更新できる状態 や体制を整えておくことが大事 8

Slide 9

Slide 9 text

PHPのバージョンアップ時にも役立ったAST Garoon開発チームが過去のバージョンアップ時に直面した課題たち PHPのリリースサイクルとバージョンアップの必要性 • PHP 8.0:比較演算子の挙動変更 20年ものの巨大レガシープロダクトをPHP 8.0にアップデートした際の対策と得られた知見 by 赤間 仁志 https://speakerdeck.com/akamah/20nian-mononoju-da-regasipurodakutowo-php-8-dot-0niatupudetositaji-nodui-ce-tode-raretazhi-jian • PHP 8.1:mb_detect_encoding()の仕様変更 Garoon開発チームではPHP8.1の仕様変更とどう向き合ってきたのか by 千葉 泰理(ぱくとま) https://speakerdeck.com/pakutoma/how-we-have-responded-to-the-php-8-dot-1-mbstring-specification-changes • PHP 8.2:動的プロパティの非推奨化 PHP 9 に備えよ - 動的プロパティ、どうすればいぃ? by 荒瀬 泰輔 https://speakerdeck.com/taisukearase/php-9-nibei-eyo-dong-de-puropatei-dousurebaii 9

Slide 10

Slide 10 text

PHPのバージョンアップ時に 参照する移行ガイド 10

Slide 11

Slide 11 text

PHPのバージョンアップ時にも役立ったAST PHPをバージョンアップする前に PHPのバージョンアップ時に参照する移行ガイド • 移行ガイドを必ず確認 • PHP 8.2の場合:https://www.php.net/manual/ja/migration82.php • 新機能だけでなく推奨されなくなる機能や下位互換性のない変更点も記載 • 移行ガイドに記載されている内容に基づいて製品への影響がないか調査 11

Slide 12

Slide 12 text

PHPのバージョンアップ時にも役立ったAST PHP 8.2で推奨されなくなる機能 PHPのバージョンアップ時に参照する移行ガイド • https://www.php.net/manual/ja/migration82.deprecated.php より • 動的なプロパティの利用 • 部分的にしかサポートされていない callable • ”${var}” / “${expr}” 形式の、文字列への値の埋め込み • 'テキストエンコーディング' QPrint, Base64, Uuencode, HTML-ENTITIES • 内部メソッド SplFileInfo::_bad_state_ex() • utf8_encode() と utf8_decode() 12

Slide 13

Slide 13 text

PHPのバージョンアップ時にも役立ったAST 製品への影響が特に大きかった推奨されなくなる機能 PHPのバージョンアップ時に参照する移行ガイド • 動的なプロパティの利用 • ”${var}” / “${expr}” 形式の、文字列への値の埋め込み 13

Slide 14

Slide 14 text

PHPのバージョンアップ時にも役立ったAST ”${var}” / “${expr}” 形式の、文字列への値の埋め込み PHPのバージョンアップ時に参照する移行ガイド • “${var}”や“${expr}”といった形式での書き方が推奨されなくなった • "$var"、"{$var}"および"{${expr}}"といった形式で今後は書いていく 必要がある 14

Slide 15

Slide 15 text

PHPのバージョンアップ時にも役立ったAST ”${var}” / “${expr}” 形式の、文字列への値の埋め込み PHPのバージョンアップ時に参照する移行ガイド • PHP 9.0ではサポートされなくなる見通し • https://wiki.php.net/rfc/deprecate_dollar_brace_string_interpolation 15

Slide 16

Slide 16 text

PHPのバージョンアップ時にも役立ったAST ”${var}” / “${expr}” 形式の、文字列への値の埋め込み PHPのバージョンアップ時に参照する移行ガイド • PHPStanで検出できなかった • https://github.com/phpstan/phpstan/issues/8744 16

Slide 17

Slide 17 text

PHPのバージョンアップ時にも役立ったAST 大量に見つかった変更すべき箇所 PHPのバージョンアップ時に参照する移行ガイド • PHPスクリプトのソースコードだけでも120万行以上ある製品 • 事前の調査で「“${var}” / “${expr}” 形式の、文字列への値の埋め込 み」だけでも434箇所変更すべき箇所が見つかっていた • PHP 8.2でPhanを使って検出(Issue Type : PhanDeprecatedEncapsVar) 17

Slide 18

Slide 18 text

PHPのバージョンアップ時にも役立ったAST 品質保証やテスト戦略をどうするべきかという課題に直面 PHPのバージョンアップ時に参照する移行ガイド • 大量に見つかった変更すべき箇所のソースコードを変更した場合に挙動が 変わらないように品質をどう担保するか • 変更する箇所すべてに対して1箇所ずつ細かくテストするのは手間や期間 を考えると現実的に無理 • テスト工数を抑えられるような良い方法はないか思案 18

Slide 19

Slide 19 text

バージョンアップ時に 挙動が変わらない根拠としてASTに着目 19

Slide 20

Slide 20 text

PHPのバージョンアップ時にも役立ったAST AST バージョンアップ時に挙動が変わらない根拠としてASTに着目 • Abstract Syntax Treeの略 • 抽象構文木 • ソースコードの構造をツリー状に表現したもの • ソースコードの解析や変換に活用できる 20

Slide 21

Slide 21 text

PHPのバージョンアップ時にも役立ったAST きっかけはPHP勉強会@東京 バージョンアップ時に挙動が変わらない根拠としてASTに着目 • PHP 8.2にバージョンアップする際の「"${var}" / "${expr}" 形式の、 文字列への値の埋め込み」についてはASTを活用できることに気づく • 2023年11月に開催された「第158回 PHP勉強会@東京」で金城さんの ASTに関する発表を聞いたことがきっかけ 21 金城さんのASTに関する発表スライドより

Slide 22

Slide 22 text

PHPのバージョンアップ時にも役立ったAST ASTのハッシュ値が同じならプログラムの変更前後で差分がないと判断可能 バージョンアップ時に挙動が変わらない根拠としてASTに着目 • 第158回 PHP勉強会@東京における金城さんのASTに関する発表 • プログラムの本質的構造を示すASTのハッシュ値が同じであればプログラムの 変更前と変更後の間に差分がないと判断できるという内容の発表 • https://speakerdeck.com/o0h/php-ast-check-diff 22 金城さんのASTに関する発表スライドより

Slide 23

Slide 23 text

PHPのバージョンアップ時にも役立ったAST 同じソースコードであればASTも同じになる バージョンアップ時に挙動が変わらない根拠としてASTに着目 23 ソースコード AST_STMT_LIST 0: AST_ASSIGN var: AST_VAR name: "var" expr: "Hello World!" 1: AST_ECHO expr: AST_ENCAPS_LIST 0: AST_VAR name: "var"

Slide 24

Slide 24 text

PHPのバージョンアップ時にも役立ったAST 同じソースコードであればASTも同じになる バージョンアップ時に挙動が変わらない根拠としてASTに着目 24 ソースコード AST_STMT_LIST 0: AST_ASSIGN var: AST_VAR name: "var" expr: "Hello World!" 1: AST_ECHO expr: AST_ENCAPS_LIST 0: AST_VAR name: "var"

Slide 25

Slide 25 text

PHPのバージョンアップ時にも役立ったAST “${var}”から”{$var}”に置き換えてもASTが変わらない=挙動も変わらない バージョンアップ時に挙動が変わらない根拠としてASTに着目 25 ソースコード AST_STMT_LIST 0: AST_ASSIGN var: AST_VAR name: "var" expr: "Hello World!" 1: AST_ECHO expr: AST_ENCAPS_LIST 0: AST_VAR name: "var"

Slide 26

Slide 26 text

PHPのバージョンアップ時にも役立ったAST ASTのハッシュ値が同じなら変更前後で挙動の変更がないと判断可能 バージョンアップ時に挙動が変わらない根拠としてASTに着目 • “${var}”から”{$var}”に機械的に置き換えてもASTが同じならソース コードの変更前後で挙動の変更もないと見なせる • 技術的に自信を持ってテスト不要と判断できる • ハッシュ値を比較に使うことで差分の有無を簡単に確認できる 26

Slide 27

Slide 27 text

PHPでASTを取得および そのハッシュ値を比較する方法 27

Slide 28

Slide 28 text

PHPのバージョンアップ時にも役立ったAST ASTの取得に使ったソフトウェア PHPでASTを取得およびそのハッシュ値を比較する方法 • PHP FoundationのボードメンバーおよびPHPコア開発者の1人である Nikita Popovさんが開発したツールを使用 • php-ast • https://github.com/nikic/php-ast • PHP-Parser • https://github.com/nikic/PHP-Parser 28 https://github.com/nikic/php-ast?tab=readme-ov-file#differences-to-php-parser

Slide 29

Slide 29 text

PHPのバージョンアップ時にも役立ったAST php-astでASTを取得するサンプル PHPでASTを取得およびそのハッシュ値を比較する方法 • php-astのutil.phpで定義されているast_dump()を使用してASTを出力 29 https://github.com/nikic/php-ast?tab=readme-ov-file#example

Slide 30

Slide 30 text

PHPのバージョンアップ時にも役立ったAST ASTを取得およびそのハッシュ値を比較する手順の流れ PHPでASTを取得およびそのハッシュ値を比較する方法 • PHP 8.1の環境にphp-astをインストール • php.iniに「extension=ast.so」(Windowsの場合には 「extension=php_ast.dll」)を追加 • php-astを使用してASTを出力 • 出力したASTからhash()を使ってハッシュ値(SHA-256)を生成 • 変更前と変更後のハッシュ値を比較して一致するか確認 30

Slide 31

Slide 31 text

ASTのハッシュ値を確認する際に 留意する点 31

Slide 32

Slide 32 text

PHPのバージョンアップ時にも役立ったAST 挙動の差が発生する理由や境界を意識する ASTのハッシュ値を確認する際に留意する点 • PHP 8.2からは非推奨を示すエラーメッセージが出力されるように変更さ れていることを考慮すると今回の用途ではPHP 8.1でphp-astを実行する 必要があった • PHP 8.1でphp-astを使った場合 • ソースコードの変更前後でASTは変わらない • ハッシュ値が一致するか確認する用途に使えた • PHP 8.2でphp-astを使った場合 • ASTおよびASTのハッシュ値が変わる • php-astを使うPhanが影響箇所を検出できたのはこのため • https://github.com/nikic/php-ast/pull/227 32

Slide 33

Slide 33 text

PHPのバージョンアップ時にも役立ったAST 複数のツールを使ってどの場合に差分が発生するか検証する ASTのハッシュ値を確認する際に留意する点 • PHP-Parserを使った場合にはPHP 8.1でもPHP 8.2でも今回対象としてい る範囲においてはASTは同じだった • 結果として • 影響箇所を検出するために内部的にphp-astを用いるPhanをPHP 8.2で使った • ASTのハッシュ値が一致するか確認する用途にphp-astをPHP 8.1で使った • 用途や目的に応じて複数のツールを使って検証することはやはり大事 33

Slide 34

Slide 34 text

PHPのバージョンアップ時にも役立ったAST PHP 8.1でphp-astを使う場合でも一部ハッシュ値が変わるケースが存在 ASTのハッシュ値を確認する際に留意する点 • PHP CS FixerやRectorによる置換ではなく、テキストエディターやIDEを 使って単に「${」を「{$」に一括置換した場合 • DocComment(/** */で括られるコメント)内にある“${var}”および “${expr}”形式で書かれている文字列を置換した場合はphp-astで取得した ASTのハッシュ値が変わる場合があった • DocComment内を置換しなかった場合にはASTのハッシュ値は同じだった • 最終的にDocComment内部での置き換えであれば挙動への影響はないと判断 34

Slide 35

Slide 35 text

PHPのバージョンアップ時にも役立ったAST PHP 8.1でphp-astを使う場合でも一部ハッシュ値が変わるケースが存在 ASTのハッシュ値を確認する際に留意する点 35 ソースコード

Slide 36

Slide 36 text

まとめ 36

Slide 37

Slide 37 text

PHPのバージョンアップ時にも役立ったAST まとめ まとめ • 実際のプロダクト開発においてPHP 8.1からPHP 8.2にバージョンアップ する作業の一部を効率化し大幅にテスト工数を削減できた • ソースコードを変更した際にASTのハッシュ値が同じなら、プログラムの 変更前後で差分がないと見なすことができ、技術的に自信を持ってテスト 不要と判断できる • アイデア次第でASTは他の場面でも役立つ可能性がある 37

Slide 38

Slide 38 text

PHPのバージョンアップ時にも役立ったAST “Connecting the dots” まとめ • 勉強会でASTのハッシュ値が同じであればプログラムの変更前と変更後の 間に差分がないと判断できるという発表を聞いたことがきっかけ • 関心を持ち続けながら勉強会に参加しているとふとしたことがきっかけで 後で役に立つことがある • 機会があればカンファレンスや勉強会に参加してみてはいかがでしょうか 38

Slide 39

Slide 39 text

©️ Cybozu, Inc. 39