PHP_CodeSniffer & VSCodeの環境を作ってみた

何かしらのコーディング規約を導入したいPHPのプロジェクトがあったので、PHP_CodeSnifferを導入してみました。その手順をまとめています。

# PHP_CodeSnifferとは？
PHP_CodeSnifferとは、特定のコーディング規約に違反していないかどうかをチェック、修正する開発ツールです。
PHP、JavaScript、CSSファイルのコーディングに関して、規約違反がないかを判定、修正することができます。

# 導入手順
### PHP_CodeSnifferの導入
Composerを使って、プロジェクトのローカルにPHP_CodeSnifferをインストール

```
composer require --dev "squizlabs/php_codesniffer=3.*"
```

## コーディング規約の設定ファイル作成
規約の設定用ファイル`.phpcs.xml.dist`をプロジェクト内に作成
中身は例です。

```xml
<?xml version="1.0"?>
<ruleset name="custom coding standard">
  <description>A custom coding standard.</description>
  <!-- PSR12準拠 -->
  <rule ref="PSR12">
  </rule>

  <!-- インデントはスペース、サイズは4 -->
  <rule ref="Generic.WhiteSpace.ScopeIndent">
    <properties>
      <property name="indent" value="4"/>
      <property name="tabIndent" value="false"/>
    </properties>
  </rule>

  <!-- 変数名をキャメルケースに -->
  <rule ref="Squiz.NamingConventions.ValidVariableName" />
  <rule ref="Squiz.NamingConventions.ValidVariableName.PrivateNoUnderscore">
      <severity>0</severity>
  </rule>

  <!-- vendorフォルダ以下のファイルはチェックしない -->
  <exclude-pattern>vendor/</exclude-pattern>
</ruleset>
```

## 動作確認
### コードのチェック
チェック用にスタイルがおかしい`HogeClass.php`ファイルを用意。

```php
<?php

class hoge_class{
  var some_value;
  
  function hoge_func(int a,int b){
        $hoge_value = 1;
return 3;
  }
}
```

`phpcs`コマンドで、`HogeClass.php`をチェックします。

```
./vendor/bin/phpcs HogeClass.php
```

エラーが検出できたら成功です。

```
---------------------------------------------------------------------------------------------------
FOUND 11 ERRORS AFFECTING 6 LINES
---------------------------------------------------------------------------------------------------
 3 | ERROR | [ ] Each class must be in a namespace of at least one level (a top-level vendor name)
 3 | ERROR | [ ] Class name "hoge_class" is not in PascalCase format
 3 | ERROR | [x] Opening brace of a class must be on the line after the definition
 4 | ERROR | [x] Line indented incorrectly; expected at least 4 spaces, found 2
 6 | ERROR | [x] Line indented incorrectly; expected 4 spaces, found 2
 6 | ERROR | [ ] Method name "hoge_class::hoge_func" is not in camel caps format
 6 | ERROR | [ ] Visibility must be declared on method "hoge_func"
 6 | ERROR | [x] Opening brace should be on a new line
 7 | ERROR | [ ] Variable "hoge_value" is not in valid camel caps format
 8 | ERROR | [x] Line indented incorrectly; expected at least 8 spaces, found 0
 9 | ERROR | [x] Line indented incorrectly; expected 4 spaces, found 2
---------------------------------------------------------------------------------------------------
PHPCBF CAN FIX THE 6 MARKED SNIFF VIOLATIONS AUTOMATICALLY
---------------------------------------------------------------------------------------------------

Time: 309ms; Memory: 6MB
```

### コードの自動修正
PHP_CodeSnifferには、`phpcbf`というコマンドがあります。
このコマンドは、ツールの可能な範囲でコードを修正してくれるコマンドです。
先ほどの`HogeClass.php`を修正してみます。

```
./vendor/bin/phpcbf HogeClass.php
```

`HogeClass`を確認すると、インデントの乱れなどに関して修正されているのがわかります。

```php
<?php

class hoge_class
{
    var some_value;

    function hoge_func(int a,int b)
    {
        $hoge_value = 1;
        return 3;
    }
}
```

ただ`phpcs`でチェックすると規約違反がいくつか残っているので、それらは手動で修正します。

```
-----------------------------------------------------------------------------------------------
FOUND 5 ERRORS AFFECTING 3 LINES
-----------------------------------------------------------------------------------------------
 3 | ERROR | Each class must be in a namespace of at least one level (a top-level vendor name)
 3 | ERROR | Class name "hoge_class" is not in PascalCase format
 7 | ERROR | Method name "hoge_class::hoge_func" is not in camel caps format
 7 | ERROR | Visibility must be declared on method "hoge_func"
 9 | ERROR | Variable "hoge_value" is not in valid camel caps format
-----------------------------------------------------------------------------------------------

Time: 58ms; Memory: 6MB
```

これで修正完了です。

```php
<?php

namespace hoge;

class HogeClass
{
    private $someValue;

    public function hogeFunc(int $a, int $b)
    {
        $hogeValue = 1;
        return 3;
    }
}
```



# VSCodeのプラグインでPHP_CodeSnifferと連携させる
PHP_CodeSnifferが使えるようになったが、コマンドだけだと使い勝手が悪い局面があるので、VSCodeと連携させてみます。

## phpcsプラグインをインストール
PHP_CodeSnifferと連携させるプラグインは沢山あるのですが、今回は「phpcs」と「PHP Sniffer & Beautifier」を利用します。
まずはそれぞれをinstall。

<img width="1079" alt="スクリーンショット 2020-06-22 11.02.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73712/dae8e479-0dd1-dd98-ab34-77585ca723e3.png">
<img width="1081" alt="スクリーンショット 2020-06-22 11.16.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73712/94e878ad-d12e-071d-50e1-af5cc66c0339.png">

## VSCodeの設定ファイルを作成
プロジェクト内に`.vscode/setting.json`を作成し、以下の記述を行います。
細かい設定は各プラグインの説明を確認してください。今回は適当にいくつかそれっぽいものをピックアップしています。

```json

{
    "editor.formatOnSave": true,     <-- ファイルを保存した時に、formatterが動作する
    "phpcs.enable": true,            <-- phpcsを有効にする
    "phpcs.autoConfigSearch": true,  <-- phpcsの設定ファイルを自動で検索する
    "phpsab.fixerEnable": true,      <-- phpsabの自動整形を有効にする
    "phpsab.snifferMode": "onSave",  
    "phpsab.autoConfigSearch": true,
}
```

エディタでファイルを確認した時、規約違反時には赤の波線、保存時に自動整形ができていれば設定完了です。

<img width="507" alt="スクリーンショット 2020-06-22 11.21.18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73712/5dd049b5-5ab9-797f-6240-d3ca2559c1f0.png">

# 注意点
PHP CodeSnifferの動作確認中に気づいた罠についてまとめます。

## phpcsコマンドで検出できるのは「規約違反」でありSyntaxErrorは検出できない
phpcsではphpのsyntaxErrorは検出できませんでした。CIとか回してコードの品質チェックするなら`phpcs`に加えて`php -l`使ってSyntaxチェックする方が良いかも。
ただし`php -l`も精度100%というわけではないので過信は禁物。



それでは良きPHPライフを〜