phpcs & phpcbf コマンドについてメモ

phpcs & phpcbf コマンドについてメモ
====================================

PHP コーディングルールの整理にあたり、 phpcs と phpcbf について色々触ってみたので、メモ。

あくまで、メモ程度。(**予防線**)



- - -

### 概要

phpcs / phpcbf とは下記を略したコマンド名であり、それぞれの役目は下記の通り。

* phpcs : PHP Code Sniffer
    * 設定したルールに基づき、指定したファイルのコーディングスタイルを **判定**

* phpcbf : PHP Code Beautifier and Fixer
    * 設定したルールに基づき、指定したファイルのコーディングスタイルを **整形**

phpcs / phpcbf ともにソースコードは GitHub 上の [squizlabs/PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer) で公開されている。



- - -

### インストール方法

インストール方法は [README](https://github.com/squizlabs/PHP_CodeSniffer/blob/master/README.md) に書いてある通りだが、管理のしやすさから composer でインストールした方が良さそう。

```
{
  "require-dev": {
    "squizlabs/php_codesniffer": "2.*"
  }
}
```

composer でインストールした場合は ```composer.json``` で ```"config": { "bin-dir": "bin" }``` 等の設定をしない限りは ```./vendor/bin/phpcs``` / ```./vendor/bin/phpcbf``` で実行可能となる。



- - -

### 実行方法

「実行方法」についてはヘルプ (```$ phpcs --help```) や別の記事を参考に。

ただし 1 点だけ、 CLI 実行時の引数は大体が ```ruleset.xml``` を用意して記述することで賄える為、
```ruleset.xml``` を各プロジェクトのリポジトリで管理し、
```--standard``` オプションで指定する形の実行方法で対応することをオススメする。

```
# 判定
$ phpcs   --standard=/path/to/MyStandard/ruleset.xml

# 整形
$ phpcbf  --standard=/path/to/MyStandard/ruleset.xml
```

* **【point】**
	* ```ruleset.xml``` で、かなり細かな設定ができる為、コーディングルールを文章で管理せず、設定ファイル (```ruleset.xml```) で管理することが可能となり、コーディングルールの変更などをプルリクエストの形で提案し、レビューを受け、承認され、採用される、という流れを作ることができる。

* ```ruleset.xml``` 設定方法
    * 参照 : [squizlabs/PHP_CodeSniffer/wiki](https://github.com/squizlabs/PHP_CodeSniffer/wiki)
        * [Annotated ruleset.xml](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Annotated-ruleset.xml)
        * [Advanced Usage](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Advanced-Usage) も合わせて参照



- - -

### 実行結果

```--report=csv``` や ```--report=xml``` オプションを指定して実行すると、下記の情報が得られる。

| key                   | description               |
|-----------------------|---------------------------|
| File / Line / Column  | 警告発生箇所              |
| Type                  | WARNING or ERROR          |
| Message               | 警告内容                  |
| Source                | ルール **【後述】**       |
| Severity              | 重症度                    |
| Fixable               | **phpcbf での整形可否**   |



- - -

#### Source (ルール) について

* Source は基本的に ```<STANDARD>.<CATEGORY>.<SNIFF>[.<CODE>]``` という具合に ```.``` 区切りで 4 つの要素から構成される。

* 一部、 ```<STANDARD>.<CATEGORY>.<SNIFF>``` の 3 つからなるモノもある。
    * 例 : PEAR.ControlStructures.ControlSignature など
        * 警告発生時に ```<CODE>``` の指定をしていない為？

* 判定処理は ```/path/to/<STANDARD>/Sniffs/<CATEGORY>/<SNIFF>Sniff.php``` のソースコードで処理され、内容に依って ```<CODE>``` 指定で警告される。
    * 例 : ```Generic.Files.LineLength``` の場合、 [./vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/**Generic**/Sniffs/**Files**/**LineLength**Sniff.php](https://github.com/squizlabs/PHP_CodeSniffer/blob/master/CodeSniffer/Standards/Generic/Sniffs/Files/LineLengthSniff.php) で処理される。

* 余談 : 1 行の文字数を判定している ```Generic.Files.LineLength``` のコード自体が違反している。

```
$ phpcs --sniffs=Generic.Files.LineLength ./vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Files/LineLengthSniff.php

FILE: ...r/CodeSniffer/Standards/Generic/Sniffs/Files/LineLengthSniff.php
----------------------------------------------------------------------
FOUND 0 ERRORS AND 5 WARNINGS AFFECTING 5 LINES
----------------------------------------------------------------------
  12 | WARNING | Line exceeds 85 characters; contains 94 characters
  28 | WARNING | Line exceeds 85 characters; contains 94 characters
  99 | WARNING | Line exceeds 85 characters; contains 91 characters
 117 | WARNING | Line exceeds 85 characters; contains 88 characters
 138 | WARNING | Line exceeds 85 characters; contains 91 characters
----------------------------------------------------------------------

Time: 14ms; Memory: 3.25Mb
```

* 下記のように ```ruleset.xml``` で ```<STANDARD>.<CATEGORY>.<SNIFF>``` を指定して判定値を設定することが可能
    * (ワイド画面が当たり前の時代に default 値では短い為、少し、拡張)
    * **【注意】** ```<STANDARD>.<CATEGORY>.<SNIFF>.<CODE>``` ではなく ```<STANDARD>.<CATEGORY>.<SNIFF>``` を指定して設定
        * 警告では ```<STANDARD>.<CATEGORY>.<SNIFF>.<CODE>``` が出る為、ハマらないように…。

```
<?xml version="1.0"?>
<ruleset name="...">
  ...
  <rule ref="Generic.Files.LineLength">
    <properties>
      <!--
        lineLimit           : 1 行の文字数が超過すると WARNING が発生
        absoluteLineLimit   : 1 行の文字数が超過すると ERROR が発生
        -->
      <property name="lineLimit" value="160"/>
      <property name="absoluteLineLimit" value="200"/>
    </properties>
  </rule>
  ...
</ruleset>
```



- - -

#### Source (ルール) 自作

* 神経質な人 (自分も？) にはオリジナルのコーディングルールも実装が可能なので、お試しあれ。
    * 参考 : [Manual :: A list of configuration options](http://pear.php.net/manual/en/package.php.php-codesniffer.coding-standard-tutorial.php)