PHPerのための「静的解析」を語り合うPHP TechCafe
============================================
# PHPer's NEWS
::: info
**[条件付き戻り値型とPHPStan 1.6.0の新機能](https://www.phper.ninja/entry/2022/04/28/015632)**
PHP8.1完全サポート(PHP8.1リリース後すぐにいくつかが対応されていたことを考えると対応の速さに脱帽です)
:::
::: info
**[【PHP9】ついに未定義プロパティが使えなくなる](https://qiita.com/rana_kualu/items/0defd290da5d1707f0d3)**
:::
::: info
**[Readonly classes in PHP 8.2](https://www.amitmerchant.com/readonly-classes-in-php-82/)**
:::
::: info
**[スマホゲーム業界におけるPHPの歴史とLaravel Octaneで広がるこれからのPHP](https://speakerdeck.com/cyberagentdevelopers/sumahogemuye-jie-niokeruphpfalseli-shi-tolaravel-octanedeguang-garukorekarafalsephp-cadc2022)**
単純にゲームのバックエンドをPHPで作っていたんだなということと、Octaneがなんかすごそうなので。(レベル低くてすみません)
:::
::: info
**[近況PHP / PHP in now a days](https://speakerdeck.com/uzulla/php-in-now-a-days)**
非PHPer向けと書いてあるとおりPHP言語の現在地がPHPer以外にもわかりやすくまとめられています。
:::
::: info
**[PHPカンファレンス沖縄開催決定!!](https://phpcon.okinawa.jp/)**
2022年8月27日(土)予定
:::
::: info
**[プログラム言語のPythonとPHPのライブラリが乗っ取られて悪意のあるバージョンが公開、開発者の情報が収集される](https://gigazine.net/news/20220526-aws-hijacked/)**
:::
::: info
**[The opcache optimizer](https://www.npopov.com/2022/05/22/The-opcache-optimizer.html)**
:::
# 特集:「静的解析」を語り合う
## 静的解析とは
> **Wikipedia**
> コンピュータのソフトウェアの解析手法の一種であり、実行ファイルを実行することなく解析を行うこと。
> 〜中略〜
> 静的コード解析はソースコードに対して行われることが多く、少数ながらオブジェクトコードに対して行う場合もある。
→ PHPのコードに対して、**プログラムを実行せずに**解析を行い、問題点を洗い出すこと
## 一般的な使い方
## 編集中コードの検証
IDEを利用しコーディング中に静的解析を行う
* PHP文法の誤りを表示
* 不適切コードの指摘
* コード補完
## CIに組み込む
コードを定期的/自動的に静的解析を行う
* git push 時に自動的に解析 → 不適切コードやルール違反を指摘
* コードレビュー観点が明確になる
* 人に指摘されるより気が楽 ← 重要
## PSRとの関係性
```
<補足:PSRとは>
PHP-FIG が策定しているPHPの標準規約集。
規約は各ルールがほぼ独立しており、好きな規約のみを選んで採用することができる。
https://www.php-fig.org/psr/
```
PSR-1 や PSR-2、PSR-12 はコーディング規約に関するものであるため、取り入れている静的解析ツールも多い
※ 現在、PSR-2 は非推奨
## 代表的なPHP静的解析ツール
### PHP -l ←文法チェックができるらしい
### PHP MD
* PHP MD([PHP Mess Detector](https://phpmd.org/))とは
- コードの複雑性を評価し、指摘してくれるツール。
- 以下のような問題を指摘してくれる。
- バグになりそうなコード
- 最適ではないコード
- 複雑な表現
- 未使用のパラメータ、メソッド、プロパティ
* [インストール](https://phpmd.org/download/index.html)
* 以下の方法でインストール可能
* Pharファイルをダウンロード
* Composerでインストール
* GitHubからClone
* 実行例
* phpmd [filename|directory] [report format] [ruleset file]
```
[root@vg110 core]# vendor/phpmd/phpmd/src/bin/phpmd test.php text codesize,controversial,design,naming,unusedcode
/usr/local/vanguardDev/vanguard/vg-back/core/test.php:5 CamelCaseMethodName The method test_function is not named in camelCase.
/usr/local/vanguardDev/vanguard/vg-back/core/test.php:5 CamelCaseParameterName The parameter $param_string is not named in camelCase.
/usr/local/vanguardDev/vanguard/vg-back/core/test.php:5 CamelCaseVariableName The variable $param_string is not named in camelCase.
```
* [指定可能なformat](https://phpmd.org/documentation/index.html#renderers)は以下
* xml - xml形式で出力される。
* text - テキスト形式で出力される。
* ansi - コマンドライン用のカラフルなフォーマットされたテキストで出力される。
* html - html形式で出力される。
* json - json形式で出力される。
* github - GitHub Actionsが理解できる形式で出力される。
* [組み込みのruleset](https://phpmd.org/rules/index.html#code-size-rules)は以下を指定可能。
* codesize - コードサイズ関連のルール(循環的複雑度やクラスやメソッドの大きさなど)
* controversial - 議論の余地のある部分を検出するルール(キャメルケースの使用や、スーパーグローバル変数へのアクセスなど)
* design - 設計関連のルール(クラスの依存関係や推奨されない関数の使用など)
* naming - 名前関連のルール(長すぎたり、短すぎたりする名前)
* unusedcode - 使われていないコードを検出するルール
* [カスタムのruleset](https://phpmd.org/documentation/creating-a-ruleset.html)
* xmlファイルを設置することで、rulesetのカスタマイズが可能
* 必要なrulesetのみ適用する
* ruleset内の個別のruleを削除する
* 個別のruleのプロパティの変更(最小値や最大値を変更したりとか)
### PHP CS
* PHP CS([PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer))とは
* 定義されたコーディング規約の違反を検出するスクリプト。
* PSR や PEAR といった様々なコーディング規約を指定して検査を実施できる。
* 独自の規約を追加することも可能。
* コーディング規約の違反を自動で修正する`phpcbf`も付属している。
* [インストール](https://github.com/squizlabs/PHP_CodeSniffer)
* 以下の方法でインストール可能
* Pharファイルをダウンロード
* Composerでインストール
* Phiveでインストール
* PEARでインストール
* GitHubからClone
* 実行例
```
$ phpcs /path/to/code/myfile.php
FILE: /path/to/code/myfile.php
--------------------------------------------------------------------------------
FOUND 5 ERROR(S) AND 1 WARNING(S) AFFECTING 5 LINE(S)
--------------------------------------------------------------------------------
2 | ERROR | Missing file doc comment
20 | ERROR | PHP keywords must be lowercase; expected "false" but found
| | "FALSE"
47 | ERROR | Line not indented correctly; expected 4 spaces but found 1
47 | WARNING | Equals sign not aligned with surrounding assignments
51 | ERROR | Missing function doc comment
88 | ERROR | Line not indented correctly; expected 9 spaces but found 6
--------------------------------------------------------------------------------
```
* コーディング規約の指定
```
# インストールされているコーディング規約を確認
$ phpcs -i
The installed coding standards are MySource, PEAR, PSR1, PSR12, PSR2, Squiz and Zend
# コーディング規約を指定して実行(デフォルトはPEAR)
$ phpcs --standard=PSR12 /path/to/code/myfile.inc
# デフォルトのコーディング規約を変更
$ phpcs --config-set default_standard PSR12
```
* 規約のカスタマイズ
- .phpcs.xml ファイルを設置して独自のコーディング規約を設定できる。
```
<?xml version="1.0"?>
<ruleset name="Custom Standard">
<rule ref="PSR12">
<!-- "PSR12" の中で除外するルール -->
<exclude name="Generic.Files.LineLength"/>
</rule>
<!-- 追加するルール -->
<rule ref="PEAR.WhiteSpace.ObjectOperatorIndent"/>
<!-- 除外するファイル・ディレクトリ -->
<exclude-pattern>node_modules/</exclude-pattern>
</ruleset>
```
### [PHPStan](https://phpstan.org/)
* GitHub スター数
* 11k
* composer や Dockerから利用可能なため比較的導入は簡単
* PHARをダウンロードして利用することもできる
* ただし Composerが無いと[PHPStan拡張機能](https://phpstan.org/user-guide/extension-library)は利用できない
* 解析の厳密さはオプションで指定可能
* [各ルールレベル](https://phpstan.org/user-guide/rule-levels)
* 現在10レベル(0が最も緩く、9が最も厳密)から選択可能
0. 基本的なチェック(未知のクラス、未知の関数、$this上で呼び出された未知のメソッド、これらのメソッドや関数に渡された引数の数が間違っている、常に未定義変数)
1. 未定義の可能性がある変数、__call と __get を持つクラス上の未知のマジックメソッドとプロパティ
2. 未知のメソッドを ($this だけでなく) すべての式でチェックし、PHPDocs を検証
3. 戻り値の型、プロパティに割り当てられた型
4. 基本的なデッドコードチェック - instanceof やその他の型チェックが常に偽であること、 死んだ else 分岐、return の後に到達できないコード、など
5. メソッドや関数に渡される引数の型のチェック
6. タイプヒントの欠落を報告
7. 部分的に間違ったユニオンタイプのレポート - ユニオンタイプ内のいくつかのタイプにのみ存在するメソッドを呼び出した場合、レベル7はそれをレポートするようになりました。
8. null可能な型に対するメソッド呼び出しとプロパティアクセスを報告する
9. 混合型(mixed)について厳密であること - その型でできる唯一の許可された操作は、別の混合型(mixed)に渡すことです
* [www.DeepL.com/Translator](https://www.deepl.com/Translator)(無料版)で翻訳しました。
* レベル0 で報告されたエラーをすべて解決してから次のレベルに進む、といった形でリファクタリングしていく
* とはいえ、歴史の長いプロジェクトの場合、レベル0でも相当な数のエラーが検出される可能性も・・・。
* [ベースラインについて](https://phpstan.org/user-guide/baseline)
* ある時点で実行した静的解析の結果を保持して、それ以降の静的解析の結果には報告されないようにする
* 新しいコードと変更されたコードで検知された違反のみに注力することができる
* [カスタムルール](https://phpstan.org/user-guide/baseline#introduce-custom-rules-and-hold-new-code-to-a-higher-standard)
* デフォルトでは入っていないユニークなルールを拡張で追加することができる
* [phpstan-rules](https://github.com/ergebnis/phpstan-rules)
* [phpstan-strict-rules](https://github.com/phpstan/phpstan-strict-rules)
* 備考
* [GitHub](https://github.com/phpstan/phpstan)
* オンライン上で動きをチェック可能
* https://phpstan.org/try
* [PHPStan Pro](https://phpstan.org/blog/introducing-phpstan-pro) という有償アドオンがある
* できること
* WebUIで問題箇所を表示
* 該当箇所をクリックすることでエディターを開く
* ソース修正時もバックグラウンドで解析されWebUI画面を自動的に更新
* 見つかったエラーに対して適切な修正をサポートしてくれる
* 価格(2022/05/17 時点)
* 初回30日間は無料
* 個人利用
* 月7ユーロ
* 年間プラン70ユーロ
* 開発チーム利用(最大25名まで)
* 月70ユール
* 年間プラン700ユーロ
#### [LaraStan](https://github.com/nunomaduro/larastan)
* 詳細は以下参照
* [LarastanでLaravelプロジェクトを静的解析しよう!](https://qiita.com/MasaKu/items/7ed6636a57fae12231e0)
### [Psalm](https://psalm.dev/)
* GitHub スター数
* 4.8k
* [インストール手順](https://psalm.dev/docs/running_psalm/installation/)
* composer からインストール可能
* phar も存在
* [厳密さのレベルは1~8で設定可能](https://psalm.dev/docs/running_psalm/error_levels/)
* 厳しさのレベルは PHP Stan の逆
* 1が最も厳しく、8が最もゆるい
* 検知されたルールがどういう理由で不適切なのかが説明されているため納得感がある
* 例:[AbstractMethodCall](https://psalm.dev/docs/running_psalm/issues/AbstractMethodCall/)
* [IDEに設定可能](https://psalm.dev/docs/running_psalm/language_server/)
* Emacs
* PhpStorm
* Sublime Text
* Vim & Neovim
* VS Code
* [エラー検知について](https://psalm.dev/docs/running_psalm/dealing_with_code_issues/#using-a-baseline-file)
* 特定のアノテーションを付けたり設定ファイルを作成することで検知対象外にすることも可能
* レガシーコードで手を入れる方がリスクがあるようなソースに対して有効
* [ベースラインの設定可能](https://psalm.dev/docs/running_psalm/dealing_with_code_issues/#using-a-baseline-file)
### PhpStorm
https://pleiades.io/help/phpstorm/code-inspection.html
#### 解析方法
* PHPファイルを開くだけ
* 文法の誤りや不適切コードをハイライトして教えてくれる
* 重要度によってハイライトの種類が変わるので見分けやすい
* プロファイルの編集で解析内容を編集可能
* 任意の解析を追加することも可能
* 他の静的解析ツールをインストールして解析することも可能
#### 解析例
https://www.jetbrains.com/ja-jp/phpstorm/features/php_code_editor.html
* コード補完
* 開いているプロジェクトを解析し、入力文字をサジェストしてくれる
* 重複コード検出
* git commit 前の分析
* 変更されたコードの分析
# 参考情報
PHPの現場(46. PHP と型と静的解析ツール(sji_ch / tadsan))
https://php-genba.shin1x1.com/46
PHPの静的解析いろいろ
https://qiita.com/segawa/items/57ad70eef922a9cd4978
level=0 から始める PHPStan(Larastan) 導入ガイド
https://blog.shin1x1.com/entry/getting-stated-with-phpstan