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でインストールします。
Code language: Bash (bash)$ 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/
jsやcssを除外するには、
$ ./vendor/bin/phpcs --standard=PSR12 ./web/ --ignore="*.js|*.css"
Code language: Bash (bash)
警告の [x]
つきのものは、もう一つのコマンド phpcbf で自動修正できます。
Code language: Bash (bash)$ ./vendor/bin/phpcbf --standard=PSR12 foo.php
ルールのカスタマイズ
プロジェクトの全ファイルで、キャメルケース警告などを無視したい場合は、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オプションを省略できます。
Code language: Bash (bash)$ ls phpcs.xml phpcs.xml $ ./vendor/bin/phpcs foo.php
カレントディレクトリにphpcs.xmlがない場合は、--standardオプションでphpcs.xmlを指定します。
Code language: Bash (bash)$ ./vendor/bin/phpcs --standard=../phpcs.xml foo.php
ファイルごとの警告の抑制
例えば、1行が長すぎる警告(Generic.Files.LineLength
)を
Code language: Bash (bash)19 | WARNING | Line exceeds 120 characters; contains 130 characters
ファイル全体で抑制するには、先頭に、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
Code language: plaintext (plaintext)Line exceeds 120 characters; contains 192 characters
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
Code language: plaintext (plaintext)Method name "Foo::get_xx" is not in camel caps format
メソッド名がキャメルケースではありません。
PSR1.Classes.ClassDeclaration
Code language: plaintext (plaintext)Each class must be in a file by itself and must be under a namespace (a top-level vendor name).
クラスにnamespaceを設定しましょう。
Code language: plaintext (plaintext)Each class must be in a file by itself
1クラス、1ファイル。
PSR1.Files.SideEffects
Code language: plaintext (plaintext)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.
「クラス、関数、定数の定義」と「副作用のある実行コード」を、一つのファイルに書いてはいけません。
レガシープロジェクトでは、この警告が大量にでます。
PSR2.Classes.MethodDeclaration
Code language: plaintext (plaintext)Method name "_hoge" must not be prefixed with an underscore to indicate visibility
メソッド名の先頭にアンダースコアをつけても、(privateの)可視性を示すことはできません。
Code language: plaintext (plaintext)The abstract declaration must precede the visibility declaration
abstract は、public、protected、privateより前に。
Code language: plaintext (plaintext)The final declaration must precede the visibility declaration
final は、public、protected、privateより前に。
Code language: plaintext (plaintext)The static declaration must come after the visibility declaration
final は、public、protected、privateの後ろに。
PSR2.Classes.PropertyDeclaration
Code language: plaintext (plaintext)Property name "$_x" should not be prefixed with an underscore to indicate visibility
プロパティ名の先頭にアンダースコアをつけても、(privateの)可視性を示すことはできません。
Code language: plaintext (plaintext)The var keyword must not be used to declare a property
プロパティは、varではなく、public、protected、privateを使いましょう。
Code language: plaintext (plaintext)There must not be more than one property declared per statement
カンマ区切りで、複数のプロパティを宣言しないように。1つの宣言で、1つのプロパティ。
Code language: plaintext (plaintext)The static declaration must come after the visibility declaration
static は、public、protected、privateの後ろに。
Code language: plaintext (plaintext)Visibility must be declared on property "$x"
static $x; ではなく、public static $x; としよう。
PSR12.Properties.ConstantVisibility
Code language: plaintext (plaintext)Visibility must be declared on all constants if your project supports PHP 7.1 or later
PHP 7.1以降なら、クラス定数にpublic、protected、privateの指定をしましょう。
Squiz.Classes.ValidClassName
Code language: plaintext (plaintext)Class name "foo" is not in PascalCase format
クラス名がパスカルケース(先頭大文字のキャメルケース)ではありません。
Squiz.Scope.MethodScope
Code language: plaintext (plaintext)Visibility must be declared on method "hoge"
メソッドに、public、protected、privateの指定をしましょう。