phpcsとは
PHPコードのコーディングルールチェッカー的なツールです。PSR1、PSR2、PSR12、Zend、Pearのコーディングルールを内部にもっています。
次のファイル foo.php を
<?php
class Foo {
function bar() {
return $x+1;
}
}
Code language: PHP (php)
phpcsにかけると、
$ ./vendor/bin/phpcs --standard=PSR12 foo.php
FILE: /xxx/yyy/foo.php
----------------------------------------------------------------------------------------------------
FOUND 8 ERRORS AFFECTING 5 LINES
----------------------------------------------------------------------------------------------------
1 | ERROR | [x] Header blocks must be separated by a single blank line
2 | ERROR | [ ] Each class must be in a namespace of at least one level (a top-level vendor name)
2 | ERROR | [x] Opening brace of a class must be on the line after the definition
3 | ERROR | [ ] Visibility must be declared on method "bar"
3 | ERROR | [x] Opening brace should be on a new line
4 | ERROR | [x] Expected at least 1 space before "+"; 0 found
4 | ERROR | [x] Expected at least 1 space after "+"; 0 found
6 | ERROR | [x] Expected 1 newline at end of file; 0 found
----------------------------------------------------------------------------------------------------
PHPCBF CAN FIX THE 6 MARKED SNIFF VIOLATIONS AUTOMATICALLY
----------------------------------------------------------------------------------------------------
Time: 36ms; Memory: 6MB
Code language: Bash (bash)
はじめてphpcsにかけると、警告が多くてびっくりするよ
ERRORを修正した結果
<?php
namespace Ninton;
class Foo
{
public function bar()
{
return $x + 1;
}
}
Code language: PHP (php)
インストール
composerでインストールします。
$ composer require --dev squizlabs/php_codesniffer
Code language: Bash (bash)
使い方
コーディングルールとファイルを指定します。
$ ./vendor/bin/phpcs --standard=PSR12 foo.php
Code language: Bash (bash)
ディレクトリを指定することもできます。
$ ./vendor/bin/phpcs --standard=PSR12 ./web/
Code language: Bash (bash)
jsやcssを除外するには、
$ ./vendor/bin/phpcs --standard=PSR12 ./web/ --ignore="*.js|*.css"
Code language: Bash (bash)
警告の [x]
つきのものは、もう一つのコマンド phpcbf で自動修正できます。
$ ./vendor/bin/phpcbf --standard=PSR12 foo.php
Code language: Bash (bash)
ルールのカスタマイズ
プロジェクトの全ファイルで、キャメルケース警告などを無視したい場合は、phpcs.xmlを作成します。
<?xml version="1.0"?>
<ruleset name="Local">
<description>Local</description>
<rule ref="PSR1">
<exclude name="PSR1.Methods.CamelCapsMethodName.NotCamelCaps"/>
<exclude name="PSR1.Classes.ClassDeclaration"/>
<exclude name="PSR1.Files.SideEffects"/>
</rule>
<rule ref="PSR2">
<exclude name="Squiz.Classes.ValidClassName"/>
</rule>
<rule ref="PSR12">
</rule>
</ruleset>
Code language: HTML, XML (xml)
カレントディレクトリにphpcs.xmlを作っておくと、--standardオプションを省略できます。
$ ls phpcs.xml
phpcs.xml
$ ./vendor/bin/phpcs foo.php
Code language: Bash (bash)
カレントディレクトリにphpcs.xmlがない場合は、--standardオプションでphpcs.xmlを指定します。
$ ./vendor/bin/phpcs --standard=../phpcs.xml foo.php
Code language: Bash (bash)
ファイルごとの警告の抑制
例えば、1行が長すぎる警告(Generic.Files.LineLength
)を
19 | WARNING | Line exceeds 120 characters; contains 130 characters
Code language: Bash (bash)
ファイル全体で抑制するには、先頭に、phpcs:disable
を書いておきます。
<?php
// phpcs:disable Generic.Files.LineLength
Code language: PHP (php)
特定の行だけを抑制するには、直前に phpcs:ignore
を書くか、行末に phpcs:ignore
を書きます。
<?php
// phpcs:ignore Generic.Files.LineLength
$x = "長い文字列xxxxxxxxxxxxxxxxxxxxxxxxxx";
$y = "長い文字列xxxxxxxxxxxxxxxxxxxxxxxxxx"; // phpcs:ignore Generic.Files.LineLength
Code language: PHP (php)
phpmdはクラス単位、メソッド単位の抑制ができますが、残念ながらphpcsはできません。
phpcsでは抑制したい範囲を、php:disable、php:enableで囲みます。
<?php
// phpcs:disable Generic.Files.LineLength
function foo()
{
$x = "長い文字列xxxxxxxxxxxxxxxxxxxxxxxxxx";
$y = "長い文字列xxxxxxxxxxxxxxxxxxxxxxxxxx";
}
// phpcs:enabled Generic.Files.LineLength
function bar()
{
$x = "長い文字列xxxxxxxxxxxxxxxxxxxxxxxxxx";
$y = "長い文字列xxxxxxxxxxxxxxxxxxxxxxxxxx";
}
Code language: PHP (php)
警告の一覧
Generic.Files.LineLength
Line exceeds 120 characters; contains 192 characters
Code language: plaintext (plaintext)
1行が長すぎます。
メソッドや関数の定義や呼び出しの引数並びが長い場合は、1行1引数に改行しします。
計算式に、メソッド呼び出しを含んでいて長い場合は、メソッドの結果を変数に代入してから、計算します。
ifの条件式が長い場合は、&& や || で改行したり、メソッドに分けます。
HTMLタグが長いは、タグを入れ子に改行します。それでも長い場合は、そのままにしておく、途中で改行する、1行1属性に改行するなど、好みでいいと思います。
AタグのURLクエリーが長い場合は、htmlエンコードとurlエンコードをする短い名前のヘルパー関数を用意したり、build_http_query関数を使ってヘルパー関数を用意します。
SQL文が長い場合は、文字列だけを返すメソッドに切り分けます。ユニットテストがないなら、SQL文はコピペしたままにしておきます。
巨大文字列の場合、別のphpファイルにして、requireします。このままでは表示されてしまうので、ob_start()とob_get_clean()を使って、変数にキャプチャします。
PSR1.Methods.CamelCapsMethodName
Method name "Foo::get_xx" is not in camel caps format
Code language: plaintext (plaintext)
メソッド名がキャメルケースではありません。
PSR1.Classes.ClassDeclaration
Each class must be in a file by itself and must be under a namespace (a top-level vendor name).
Code language: plaintext (plaintext)
クラスにnamespaceを設定しましょう。
Each class must be in a file by itself
Code language: plaintext (plaintext)
1クラス、1ファイル。
PSR1.Files.SideEffects
A file should declare new symbols (classes, functions, constants, etc.) and cause no other side effects, or it should execute logic with side effects, but should not do both. The first symbol is defined on line 5 and the first side effect is on line 3.
Code language: plaintext (plaintext)
「クラス、関数、定数の定義」と「副作用のある実行コード」を、一つのファイルに書いてはいけません。
レガシープロジェクトでは、この警告が大量にでます。
PSR2.Classes.MethodDeclaration
Method name "_hoge" must not be prefixed with an underscore to indicate visibility
Code language: plaintext (plaintext)
メソッド名の先頭にアンダースコアをつけても、(privateの)可視性を示すことはできません。
The abstract declaration must precede the visibility declaration
Code language: plaintext (plaintext)
abstract は、public、protected、privateより前に。
The final declaration must precede the visibility declaration
Code language: plaintext (plaintext)
final は、public、protected、privateより前に。
The static declaration must come after the visibility declaration
Code language: plaintext (plaintext)
final は、public、protected、privateの後ろに。
PSR2.Classes.PropertyDeclaration
Property name "$_x" should not be prefixed with an underscore to indicate visibility
Code language: plaintext (plaintext)
プロパティ名の先頭にアンダースコアをつけても、(privateの)可視性を示すことはできません。
The var keyword must not be used to declare a property
Code language: plaintext (plaintext)
プロパティは、varではなく、public、protected、privateを使いましょう。
There must not be more than one property declared per statement
Code language: plaintext (plaintext)
カンマ区切りで、複数のプロパティを宣言しないように。1つの宣言で、1つのプロパティ。
The static declaration must come after the visibility declaration
Code language: plaintext (plaintext)
static は、public、protected、privateの後ろに。
Visibility must be declared on property "$x"
Code language: plaintext (plaintext)
static $x; ではなく、public static $x; としよう。
PSR12.Properties.ConstantVisibility
Visibility must be declared on all constants if your project supports PHP 7.1 or later
Code language: plaintext (plaintext)
PHP 7.1以降なら、クラス定数にpublic、protected、privateの指定をしましょう。
Squiz.Classes.ValidClassName
Class name "foo" is not in PascalCase format
Code language: plaintext (plaintext)
クラス名がパスカルケース(先頭大文字のキャメルケース)ではありません。
Squiz.Scope.MethodScope
Visibility must be declared on method "hoge"
Code language: plaintext (plaintext)
メソッドに、public、protected、privateの指定をしましょう。