PHP_CodeSnifferとPHPCompatibilityでコーディング標準と互換性のチェック

#概要
・PHPのコーディング標準（規約）チェック
・PHPのバージョンアップに伴う互換性チェック

を行うため、PHP_CodeSnifferとPHPCompatibilityを使ったときのメモです。

[作業環境]
Windows10
PHP5.4以上（必須）

[必要なもの]
Composer
Git

#PHP_CodeSnifferとは
コーディング規約（PEARやPSRなど）に沿った構文チェックのためのツールです。
Github：[PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer)

- コーディング標準（規約）に違反している箇所の検出（phpcs）
- コーディング標準（規約）に違反している箇所を自動的に修正（phpcbf）

などを行うことができます。

PHP_CodeSnifferには「PEAR, PSR1, PSR12, PSR2, Squiz, Zend」などのコーディング標準（規約）がデフォルトで用意されており、Wordpressなどの規約を追加することも可能です。

今回は違反の検出を行う`phpcs`コマンドについてのみ書いています。

#PHPCompatibilityとは
PHPのバージョン間の互換性をチェックしてくれるPHPCodeSnifferの追加ルールのようなものです。
コードを分析して、PHPの上位バージョンと下位バージョンとの互換性を確認できます。
Github：[PHPCompatibility](https://github.com/PHPCompatibility/PHPCompatibility)

#インストール
まずは2つをインストールしていきます。
インストールにはComposerを使用します。

##PHP_CodeSniffer
以下のコマンドを実行します。

私の場合
`C:/Users/username/AppData/Roaming/Composer`
にインストールされているのが分かります。

（パスは環境によって異なります。）

```bash
$ composer global require squizlabs/php_codesniffer
Changed current directory to C:/Users/username/AppData/Roaming/Composer
Using version ^3.5 for squizlabs/php_codesniffer
./composer.json has been created
Running composer update squizlabs/php_codesniffer
Loading composer repositories with package information
Updating dependencies
Lock file operations: 1 install, 0 updates, 0 removals
  - Locking squizlabs/php_codesniffer (3.5.8)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
  - Installing squizlabs/php_codesniffer (3.5.8): Extracting archive
Generating autoload files
```

###使い方
これで、`phpcs`コマンドが使えるようになります。

```bash
$ phpcs --version
PHP_CodeSniffer version 3.5.8 (stable) by Squiz (http://www.squiz.net)
```
　
`-i`でチェック可能なコーディング標準を確認できます。

```bash
$ phpcs -i
The installed coding standards are MySource, PEAR, PSR1, PSR12, PSR2, Squiz and Zend
```
　
コーディング標準をチェックする場合はファイルやディレクトリを指定します。
実行すると、行数と違反内容が出力されます。

```bash
$ phpcs /path/to/code/myfile.php
FILE: /path/to/code/myfile.php
-----------------------------------------------------------------------------------------------------------------
FOUND 25 ERRORS AND 5 WARNINGS AFFECTING 21 LINES
-----------------------------------------------------------------------------------------------------------------
   1 | ERROR   | [ ] Missing file doc comment
  31 | ERROR   | [ ] Missing @return tag in function comment
  39 | ERROR   | [x] Line indented incorrectly; expected 8 spaces, found 12
  42 | ERROR   | [x] Line indented incorrectly; expected 8 spaces, found 12
  45 | ERROR   | [x] Line indented incorrectly; expected 8 spaces, found 12
  52 | ERROR   | [ ] Missing @return tag in function comment
  53 | ERROR   | [x] Opening brace should be on a new line
  59 | ERROR   | [ ] Missing @return tag in function comment
  66 | WARNING | [ ] Line exceeds 85 characters; contains 93 characters
 209 | WARNING | [ ] Line exceeds 85 characters; contains 93 characters
 256 | WARNING | [ ] Line exceeds 85 characters; contains 89 characters
-----------------------------------------------------------------------------------------------------------------
PHPCBF CAN FIX THE 11 MARKED SNIFF VIOLATIONS AUTOMATICALLY
-----------------------------------------------------------------------------------------------------------------
```
　　
コーディング標準のデフォルトは`PEAR`です。
`--standard=`オプションで他を指定することも可能です。

```bash
$ phpcs --standard=PSR12 /path/to/code-directory
```
　
その他のオプションは以下で確認できます。

```bash
$ phpcs -h
```

##PHPCompatibility
次にPHPCompatibilityインストールします。

```bash
$ composer global require phpcompatibility/php-compatibility
Changed current directory to C:/Users/username/AppData/Roaming/Composer
Using version ^9.3 for phpcompatibility/php-compatibility
./composer.json has been updated
Running composer update phpcompatibility/php-compatibility
Loading composer repositories with package information
Updating dependencies
Lock file operations: 1 install, 0 updates, 0 removals
  - Locking phpcompatibility/php-compatibility (9.3.5)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
  - Downloading phpcompatibility/php-compatibility (9.3.5)
  - Installing phpcompatibility/php-compatibility (9.3.5): Extracting archive
2 package suggestions were added by new dependencies, use `composer suggest` to see details.
Generating autoload files
```
　
`--standard=PHPCompatibility`を指定して実行してみます。
もし以下のエラーが出る場合は`git clone`でPHPCompatibilityをインストールします。

```
$ phpcs -p index.php --standard=PHPCompatibility --runtime-set testVersion 7.4
ERROR: the "PHPCompatibility" coding standard is not installed. The installed coding standards are MySource, PEAR, PSR1, PSR12, PSR2, Squiz and Zend
```
　
【gitでインストールする場合】
ComposerのvendorからPHP_CodeSnifferの`Standards`ディレクトリに移動します。
先ほどPHP_CodeSnifferがインストールされていた場所の中にあるので、私の場合以下になります。

```
C:/Users/username/AppData/Roaming/Composer/vendor/squizlabs/php_codesniffer/src/Standards
```
　
`Standards`の中には他のコーディング標準が入っています。

```
$ ls
Generic/  MySource/  PEAR/  PSR1/  PSR12/  PSR2/  Squiz/  Zend/
```
　
`Standards`ディレクトリに移動したら`git clone`します。

```
$ git clone https://github.com/PHPCompatibility/PHPCompatibility.git
Cloning into 'PHPCompatibility'...
remote: Enumerating objects: 22702, done.
remote: Total 22702 (delta 0), reused 0 (delta 0), pack-reused 22702
Receiving objects: 100% (22702/22702), 6.12 MiB | 1.93 MiB/s, done.
Resolving deltas: 100% (17544/17544), done.
```
　
cloneしたPHPCompatibilityのパスを設定します。

```bash
$ phpcs --config-set installed_paths ~/AppData/Roaming/Composer/vendor/squizlabs/php_codesniffer/src/Standards/PHPCompatibility
Using config file: C:\Users\username\AppData\Roaming\Composer\vendor\squizlabs\php_codesniffer\CodeSniffer.conf

Config value "installed_paths" added successfully
```
　
以下でPHPCompatibilityが表示されればOKです。

```bash
$ phpcs -i
The installed coding standards are MySource, PEAR, PSR1, PSR12, PSR2, Squiz, Zend and PHPCompatibility
```
　
それでも以下のエラーになる場合、PHPCompatibilityのブランチを変更します。

```bash
$ phpcs -p index.php --standard=PHPCompatibility --runtime-set testVersion 7.4
ERROR: Referenced sniff "PHPCS23Utils" does not exist

Run "phpcs --help" for usage information
```
　
StandardsディレクトリからPHPCompatibilityに移動します。
`devlop`ブランチになっているはずなので`master`にチェックアウトします。

```bash
$ cd PHPCompatibility

$ git branch
develop

$ git checkout master
```
参考：[PHPCSとWordPressの標準を使用する - PHPCSと標準の更新](https://tabernawp.com/utilizando-phpcs-estandares-wordpress-2020-06-18.html)
　
これでPHPCompatibilityが指定できるようになったかと思います。
 
##使い方
`--standard=PHPCompatibility`を指定して実行します。
`-p`は実行の進行状況を表示してくれるオプションです。

```bash
$ phpcs -p /path/to/code/myfile.php --standard=PHPCompatibility --runtime-set testVersion 7.4
.......W.W...WW.............................................  60 / 213 (28%)
.....................................................W...... 120 / 213 (56%)
............................................................ 180 / 213 (85%)
...........W.....................                            213 / 213 (100%)


FILE: /path/to/code/myfile.php
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

FOUND 0 ERRORS AND 4 WARNINGS AFFECTING 4 LINES
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 210 | WARNING | Use of deprecated PHP4 style class constructor is not supported since PHP 7.
 262 | WARNING | INI directive 'track_errors' is deprecated since PHP 7.2
 268 | WARNING | The variable '$php_errormsg' is deprecated since PHP 7.2; Use error_get_last() instead
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Time: 137ms; Memory: 10MB
```
　
このように行数とエラーを表示してくれます。
非推奨になった関数などを教えてくれるので、これらを確認して修正をかけていきます。

コマンドの後ろに`> ファイル名`を付ければ結果をファイルに出力できます。

```
$ phpcs -p index.php --standard=PHPCompatibility > result.txt
```

もちろんPHPCompatibilityだけでは拾いきれないものもあるので、バージョンアップの情報を確認して手動で変更箇所を探すことも重要です。

#VScodeでPHP_CodeSnifferを使う
VScodeの拡張機能でコーディング標準をチェックすることができます。
PHP_CodeSnifferをインストールしていれば使うことが可能です。

`phpcs`という拡張機能をインストールします。
![a30c0c8aa023f36fbf9c071ec6ac591d.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/655954/2e51a55e-4bfb-bee8-6f2b-d49c5e34c20a.png)

ファイルを開くと、コーディング標準違反の箇所に指摘が入ります。
違反箇所があるとファイル名も赤くなります。
![43e2825dbab7d369e7d835b1959450db.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/655954/e595849d-bd29-2a30-6b29-b216f145ddfc.png)
　
`設定>拡張機能>PHP CodeSniffer`で設定変更も可能です。
コーディング標準（Standard）の変更や除外ファイルを指定できます。

コーディング標準を`PSR12`に変更する場合は、以下から`settings.json`を開きます。
![267f06fe122d7668dc6713cb5b637f87.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/655954/470425ff-bc96-4324-3a1e-f003de084874.png)

`phpcs.standard`に指定したい規約名を指定します。

```
"phpcs.standard": "PSR12" 
```


#参考
- [PHP: PHPの静的解析(phpcs, phpmd, etc...)](http://algo13.net/php/tips/static-analysis.html)
- [Visual Studio CodeのためのPHP_CodeSnifferであるphpcsを使ってコーディング規約をチェック](https://aipercent.net/vscode/install-phpcs/)
- [PHP_CodeSniffer で特定の PHP バージョンと互換性があるコードかをチェックする](https://www.d-wood.com/blog/2019/08/06_11431.html)
- [phpcsのおさらい: コードのチェックと自動整形を使って快適なWordPressテーマ・プラグイン開発をしよう その1](https://blog.photosynthesic.jp/2021/01/phpcs-wordpress-01/)
- [LaravelにPHP_CodeSnifferを導入しコーディング規約（PSR）に沿った記述を行う](https://www.ritolab.com/entry/188)
- [PHPCompatibility で非互換になった項目を静的解析する](https://kakakakakku.hatenablog.com/entry/2016/08/12/203545)
- [PHP_CodeSnifferを用いたphpアプリケーションの互換性チェック](https://qiita.com/zeriyoshi/items/4487e4bf3aca8b432ade)
- [PHPコーディング規約まとめ](https://qiita.com/hshimo/items/04be1f432240c58300f4)