WordPressの案件には是非コーディング規約を導入してください！

この記事は[WordPress Advent Calendar 2017](https://qiita.com/advent-calendar/2017/wordpress) 12日目へのエントリーです。
# コーディング規約について
## はじめに
コーディング規約使ってますか？
コーディング規約はPHPやHTMLを書くときのルールです。
日本語には句読点やカギカッコ、字下げなどに一定のルールがあります。英語でもカンマ、ピリオドの打ち方、スペーシングの使い方にルールがあります。
プログラムやHTMLコードでもそれぞれのルールがあり、そのルールをまとめたものがコーディング規約と呼ばれています。
その規約を守ることで可読性の高いコードを書くことができます。特に複数人でコードを見る機会がある場合にはとても便利になります。
またコーディング規約には明確な「答え」があるので、迷うことが少ないです。
答えに沿ってコーディングをすればよいので、コーディングのレベルアップにつながるなー、と思っています。

以前使い方を記事にしましたが、改めて実務で使ってみましたので、その手順についてまとめてみました。

## なぜコーディング規約を導入するか
コーディング規約は「コードを読みやすくすること」です。
コードを読みやすくするメリットは下記のとおりです。

* 他人、特にチームメンバーで読みやすい
* バグを防ぎやすい
* 未来の自分にも優しい

他人の書いたコードは本当に読みにくいですよね。

## WordPressのコーディング規約
ひとえにコーディング規約と言っても、言語ごと、環境ごとに色々な規約があります。
WordPressではそれ独自のコーディング規約が定義されています。

https://wpdocs.osdn.jp/WordPress_コーディング基準

| 規約 | URL |
|------|-----|
| CSS コーディング規約 | https://wpdocs.osdn.jp/CSS_コーディング規約 |
| HTML コーディング規約 | https://wpdocs.osdn.jp/HTML_コーディング規約 |
| JavaScript コーディング規約 | https://wpdocs.osdn.jp/JavaScript_コーディング規約 |
| PHP コーディング規約  | https://wpdocs.osdn.jp/PHP_コーディング規約 |

ざっくり全体的な特徴を述べると、

* スペースは多めに開ける（丸括弧、波括弧の前後など）
* 改行も多めに入れる（CSSセレクタ、メソッド類）

です。
ちなみにそれぞれの定義はそれほど長くないので、是非とも一読されることをおすすめします。

![Screen Shot 2017-12-12 at 22.31.27.png](https://qiita-image-store.s3.amazonaws.com/0/47327/28de2a20-fe1b-c7b4-aff6-79101efa14bd.png)


# 導入方法
## WordPressのファイル構成
今回想定しているのは「WordPressによるテーマ作成プロジェクト」です。
実際に仕事でWordPressプロジェクトの場合、多くはテーマ作成かなと思います。

今回例として作成するテーマは _s を使って作りました。

https://underscores.me

![Screen Shot 2017-12-12 at 9.00.15.png](https://qiita-image-store.s3.amazonaws.com/0/47327/59b4a0f5-478e-0263-b993-4866cb5a0005.png)

ファイル構成はこんな感じです。

![Screen Shot 2017-12-12 at 9.00.39.png](https://qiita-image-store.s3.amazonaws.com/0/47327/8d25395f-46bf-7e7e-98e5-73bd7946e456.png)

今回のリポジトリはこちらに置いてみました。

https://github.com/yousan/wpcs-1


## ComposerでのPHPCS、WPCS、PHP Compatibilityのインストール
では実際にWordPressのテーマにPHPCSを適用してみます。

まずはComposerでPHPCS (PHP Code Sniffer) をインストールします。
Composerではマシン環境全体にインストールする「グローバルインストール」と、プロジェクトごと（リポジトリごと）にインストールする「ローカルインストール」があります。
（「グローバル」という名称は見かけますが、「ローカル」の名称が違っていたらごめんなさい 参考: https://getcomposer.org/doc/00-intro.md#locally ）

```bash
$ composer require --dev squizlabs/php_codesniffer
```

続いてWordPressのコーディング規約のセットをインストールします。
https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards

このコーディング規約のルールセットは WPCS (WordPress Coding Standards)という略称が使われています。

```bash
$ composer require --dev wp-coding-standards/wpcs
```

続いてPHPのバージョンごとの言語互換性をチェックするルールセット、PHP Compatibilityをインストールします。
https://github.com/wimg/PHPCompatibility

```bash
$ composer require --dev wimg/php-compatibility
```

ここまでできたら`phpcs -i`で導入されたルールセットについて確認しておきます。

![Screen Shot 2017-12-12 at 9.18.57.png](https://qiita-image-store.s3.amazonaws.com/0/47327/78c093cc-cb31-bbe5-c9df-dda855a71c11.png)



## PHPCSにWPCS、PHP Compatibilityのルールセットを追加
続いて、最初にインストールしたPHPCSに、WPCS、PHP Compatibilityのルールセットを設定します。

```bash
$ ./vendor/bin/phpcs --config-set installed_paths `pwd -P`/vendor/wp-coding-standards/wpcs,`pwd -P`/vendor/wimg/php-compatibility
```

僕は何度もPHPCSを使ってきましたが、このルールセットの追加で躓くことが多かったので注意が必要です。

注意すべき点を下記に列挙します。

1. 呼び出すPHPCSの実行ファイルの場所に注意すること。（PHPCSをグローバルインストールした場合とローカルインストールした場合で違う。今回はローカル。）
1. 追加するルールセットは絶対パス（若しくはPHPCSをからの相対パス）で記述すること。問題回避のために絶対パスの方が良さそう。
1. --config-set で設定した値はconfファイルで確認できる。
1. 複数のルールセットを定義する場合にはカンマ区切り。

今回はComposerでローカルインストールを行ったので、`./vendor/bin/phpcs`を呼び出してコンフィグをセットします。
ここでグローバルな`phpcs`を呼んでしまうと別の設定になってしまうので注意が必要です。

追加されるルールセットは絶対パスが良いです。
特にリポジトリルートの絶対パスを調べる`pwd -P`を基に設定すると間違いが起こりにくいです。
（例 `pwd -P`/vendor/wimg/php-compatibility ）

`--config-set`は`CodeSniffer.conf`のファイルに書き出します。
うまく動かない場合にはこちらを確認すると良いです。

```php
$ cat ./vendor/squizlabs/php_codesniffer/CodeSniffer.conf
<?php
 $phpCodeSnifferConfig = array (
  'installed_paths' => '/Users/yousan/git/wpcs-1/vendor/wp-coding-standards/wpcs,/Users/yousan/git/wpcs-1/vendor/wimg/php-compatibility',
)
?>
```

## 実際に動かしてみる
_sのテーマファイルの場合、phpcs.xmlがサンプルでついてきています。
そちらを基に動かしてみます。

下記のコマンドで動かすことができます。

```
$ ./vendor/bin/phpcs --standard=./themes/wpcs/phpcs.xml
```

![Screen Shot 2017-12-12 at 9.19.16.png](https://qiita-image-store.s3.amazonaws.com/0/47327/5fb6e9e1-7752-4d8b-36e5-d5f15f687424.png)


動きましたね！

エラーがたくさん出てきました。
これらのエラーを直していくことになります。


またエラーメッセージの下の方に「自動整形できるよ！」ということが書かれています。
実は簡単なコーディング規約違反については、PHPCSに同梱のPHPCBF (PHP Beautifier and Fixer) で修正できます。
ということで自動整形を行ってみます。

```bash
$ ./vendor/bin/phpcbf --standard=./themes/wpcs/phpcs.xml
```

![Screen Shot 2017-12-12 at 9.21.47.png](https://qiita-image-store.s3.amazonaws.com/0/47327/4a180658-d784-2f4d-a5b4-64e4562d4e92.png)


すごいですね！

Gitで実際にどういった箇所が直されたのか確認できます。

![Screen Shot 2017-12-12 at 22.36.54.png](https://qiita-image-store.s3.amazonaws.com/0/47327/39e55276-7622-a1c1-7b92-c701481f48c9.png)


https://github.com/yousan/wpcs-1/commit/47b521c38126bf5bf9d061b7ce8d946e632196f0

## Composerによるアップデート時にconfigが上書きされてしまう件と解決方法

上で行った通り、PHPCSでは設定ファイルをvendor配下のconfigファイルに保存しています。
そのため composer update や composer install を行うとそのconfigファイルが上書きされて動かなくなってしまうことがあります。

それを防ぐために composer update や composer install を行った際に再度設定をするようにします。

```json:composer.json
   "scripts": {
        "post-update-cmd": [
            "phpcs --config-set installed_paths `pwd -P`/vendor/wp-coding-standards/wpcs,`pwd -P`/vendor/wimg/php-compatibility"
        ],
        "post-install-cmd": [
            "phpcs --config-set installed_paths `pwd -P`/vendor/wp-coding-standards/wpcs,`pwd -P`/vendor/wimg/php-compatibility"
        ],
    ...
```



## どの規約を適用するか
ここまで適用してきたPHPCSでは、themes/wpcs/にあるphpcs.xmlというファイルを使っていました。
`phpcs`コマンドでは--standardで与える設定XMLファイルを基に、どういった規約を適用するか、ということを決めることが出来ます。

WordPressではコーディング規約を定めていますが、プロジェクトによっては外したい規約もあるかと思います。
実際に僕が外している規約について紹介します。

| ルール名 | 概要 |
|---------|-----|
| WordPress.Files.FileName.InvalidClassFileName | 固定ページ内にクラスを入れることを許容。他から参照されない固定ページで完結するビューのコントロールロジック（ビジネスロジックはNG!）の場合、固定ページ内に書いたほうがキレイになるので許容しています。 |
| WordPress.Files.FileName.NotHyphenatedLowercase | 固定ページのスラッグにアンダースコアを許容。 |
| WordPress.XSS.EscapeOutput.OutputNotEscaped | HTMLのエスケープ漏れを許容。こちらはできれば無効化しないでスタートするほうが良いです。 |
| WordPress.VIP.AdminBarRemoval.RemovalDetected | 管理バー非表示を許容。 |
| Squiz.Commenting.InlineComment.InvalidEndChar | コメント文の末尾にピリオド類が無いことを許容。日本語句点や一文のみ体言止めの場合にはいらないので外しています。 |
| Generic.Commenting.DocComment.ShortNotCapital | コメント文を大文字で始めないことを許容。こちらもできれば外さないほうが良い。コメントに iframe といった HTMLタグなどの用語に対応のため外しました。|


下記は実際にプロジェクトでつかった設定ファイルです。

```xml
    <!-- Include the WordPress ruleset, with exclusions. -->
    <rule ref="WordPress">
        <!-- _sのルールセットを参照 @link https://github.com/Automattic/_s/blob/master/codesniffer.ruleset.xml -->
        <exclude name="Generic.WhiteSpace.ScopeIndent.IncorrectExact" />
        <exclude name="Generic.WhiteSpace.ScopeIndent.Incorrect" />
        <!-- 長めの関数の呼び出し時に複数行にしなければならない制約を無視 -->
        <exclude name="PEAR.Functions.FunctionCallSignature.Indent" />

        <!--<exclude name="Generic.WhiteSpace.ScopeIndent.IncorrectExact" />-->
        <!--<exclude name="Generic.WhiteSpace.ScopeIndent.Incorrect" />-->
        <!--<exclude name="Squiz.Commenting.ClassComment" />-->
        <!--<exclude name="Squiz.Commenting.FunctionComment" />-->
        <!--<exclude name="Generic.Commenting.DocComment" />-->
        <exclude name="WordPress.VIP" />

        <!-- 固定ページ内にクラスを入れることを許容 -->
        <exclude name="WordPress.Files.FileName.InvalidClassFileName" />
        <!-- ファイル名の決定時にslugをサポートするため、page-hoge_fuga.php を許容する -->
        <exclude name="WordPress.Files.FileName.NotHyphenatedLowercase" />
        <!-- HTML系のエスケープ強制を無視 -->
        <exclude name="WordPress.XSS.EscapeOutput.OutputNotEscaped" />

        <!-- 管理バーの非表示を許容 -->
        <exclude name="WordPress.VIP.AdminBarRemoval.RemovalDetected" />

        <!-- コメント分の末尾をフルストップ、ビックリマークやはてなで終わらせる必要があるルールを除外する -->
        <exclude name="Squiz.Commenting.InlineComment.InvalidEndChar" />
        <exclude name="Squiz.Commenting.FunctionComment.ParamCommentFullStop" />

        <!-- コメント文は大文字で始める制約を除外 ex.) iframeについて -->
        <exclude name="Generic.Commenting.DocComment.ShortNotCapital" />

        <!-- _sのテーマに元々ある多言語化周りの警告を無視する -->
        <exclude name="WordPress.WP.I18n.MissingTranslatorsComment" />

        <!-- PHPの開始タグ、閉じタグ <?phpと?> を独立した行に置かなければならない条件を除外 -->
        <exclude name="Squiz.PHP.EmbeddedPhp.ContentAfterOpen" />
        <exclude name="Squiz.PHP.EmbeddedPhp.ContentAfterEnd" />
        <exclude name="Squiz.PHP.EmbeddedPhp.ContentBeforeOpen" />
        <exclude name="Squiz.PHP.EmbeddedPhp.ContentBeforeEnd" />

        <!-- 引数の説明を省略可能にする -->
        <exclude name="Squiz.Commenting.FunctionComment.MissingParamTag" />
    </rule>
```


# 導入してみて
## 導入してみての感想
ここ数年、僕が抱えるプロジェクトが徐々に大きくなり、僕がリーダーとして複数人で開発するケースが増えてきていました。
WordPressに限りませんが、コミットされるコード、バグのトラブルシュートのヘルプ、欠員時など、プロジェクトの責任者は全てのコードを見る必要があります。
ですがコードにはエンジニアのクセがあり、こだわりがあり、どうしても読みづらく感じていました。そこでその解消のためWordPressのプロジェクトにPHPCSを導入しました。
WordPressのコーディング規約のWiki自体は「コレに合わせましょう」ということで周知していましたが、人の目ですとどうしても守ってもらえないことが多かったです。
PHPCSを使うことでチームメンバーにほぼ強制化できたため、とても便利でした。
PHPCSありがとう！

特にPHPCSはCIに組み込むことができます。チームメンバーにプルリクエストを投げて貰う前にPHPCSをテストとして通すことで、コーディング規約違反を排除することができました。
すごくありがたかったです。

というわけでみなさんも良い自動化ライフを！


明日は @ozy-san さんによる「ConoHaへWordPressをOPCache&APCu&SSLで移行と新規セットアップ」です。