はじめに
昨年からプログラムの品質を担保する取り組みの一環として、PHP_CodeSnifferでコーディング規約に準拠しているかチェックする運用を開発に取り入れました。今回はPHP_CodeSnifferの導入からチェックの実行までの流れを共有したいと思います。
環境
- Amazon Linux2
- PHP8.2.3
- Composer v2.5.8
チェック内容
今回は下記の内容に準拠しているかチェックしてみます。
- PSR-12
- 認知的複雑度が10以下か
- 厳密な型付けが有効になっているか
導入手順
インストール
composer require --dev rarst/phpcs-cognitive-complexity squizlabs/php_codesniffer dealerdirect/phpcodesniffer-composer-installer
※コマンド実行後下記が表示されるため、yを入力する必要があります。
Do you trust “dealerdirect/phpcodesniffer-composer-installer” to execute code and wish to enable it now? (writes “allow-plugins” to composer.json) [y,n,d,?]
設定ファイルの作成
プロジェクト直下に.phpcs.xmlを作成し、下記内容を記載します。
.phpcs.xml
<?xml version="1.0"?>
<ruleset name="CustomStandard">
<!-- PSR-12チェック -->
<rule ref="PSR12"/>
<!-- 厳格な型付けチェック -->
<rule ref="Generic.PHP.RequireStrictTypes" />
<!-- 認知的複雑度チェック -->
<rule ref="CognitiveComplexity.Complexity.MaximumComplexity">
<properties>
<property name="maxCognitiveComplexity" value="10" /> <!-- value="許容する複雑度の閾値" -->
</properties>
</rule>
</ruleset>
チェックの実行
チェック内容に準拠しているか確認するためのサンプルコードを用意しました。
└src
└Psr12.php
└StrictTypes.php
└CognitiveComplexity.php
サンプルコード(チェック内容に非準拠)
Psr12.php
<?php
declare(strict_types=1);
/**
* PSR-12チェック
*/
function hoge(bool $flg=true, int $num): string
{
echo "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890";
return ((integer)"12345") + 1;
}
StrictTypes.php
<?php
/**
* 厳格な型付けチェック
*/
echo 'test';
CognitiveComplexity.php
<?php
declare(strict_types=1);
/**
* 認知的複雑度チェック
*/
function countEvenOdd(array $arr): array
{
$evenCount = 0;
$oddCount = 0;
$totalOps = 0;
foreach ($arr as $value) {
for ($i = 0; $i < $value; $i++) {
for ($j = 0; $j < $value; $j++) {
for ($k = 0; $k < $value; $k++) { $totalOps++; } } } if ($value % 2 === 0) { $evenCount++; } else { $oddCount++; } } return ["even" => $evenCount, "odd" => $oddCount, "totalOps" => $totalOps];
}
プロジェクト直下に移動し、下記コマンドを実行してコーディング規約に準拠しているかチェックします。
vendor/bin/phpcs src/
コマンドの実行結果として非準拠の内容が出力されます。
FILE: /var/www/pj/src/StrictTypes.php
----------------------------------------------------------------------
FOUND 1 ERROR AFFECTING 1 LINE
----------------------------------------------------------------------
1 | ERROR | Missing required strict_types declaration
----------------------------------------------------------------------
FILE: /var/www/pj/src/Psr12.php
------------------------------------------------------------------------------------------------------------------------
FOUND 4 ERRORS AND 1 WARNING AFFECTING 3 LINES
------------------------------------------------------------------------------------------------------------------------
9 | ERROR | [x] Incorrect spacing between argument "$flg" and equals sign; expected 1 but found 0
9 | ERROR | [x] Incorrect spacing between default value and equals sign for argument "$flg"; expected 1 but found 0
9 | ERROR | [ ] Arguments with default values must be at the end of the argument list
11 | WARNING | [ ] Line exceeds 120 characters; contains 122 characters
13 | ERROR | [x] Short form type keywords must be used. Found: (integer)
------------------------------------------------------------------------------------------------------------------------
PHPCBF CAN FIX THE 3 MARKED SNIFF VIOLATIONS AUTOMATICALLY
------------------------------------------------------------------------------------------------------------------------
FILE: /var/www/pj/CognitiveComplexity.php
---------------------------------------------------------------------------------------------------
FOUND 1 ERROR AFFECTING 1 LINE
---------------------------------------------------------------------------------------------------
9 | ERROR | Cognitive complexity for "countEvenOdd" is 13 but has to be less than or equal to 10.
---------------------------------------------------------------------------------------------------
Time: 49ms; Memory: 6MB
サンプルコード(チェック内容に準拠するよう修正)
コーディング規約に非準拠の内容を修正します。
Psr12.php
<?php
declare(strict_types=1);
/**
* PSR-12チェック
*/
function hoge(int $num, bool $flg = true): string // 修正:引数と=の間にスペース追加、デフォルト引数を末尾に移動
{
echo "12345678901234567890123456789012345678901234567890'
. 123456789012345678901234567890123456789012345678901234567890"; // 修正:1行あたり120文字
return ((int)"12345") + 1; // 修正:integer→int
}
StrictTypes.php
<?php
declare(strict_types=1);
// 修正:↑厳格な型付けを有効にする宣言追加
/**
* 厳格な型付けチェック
*/
echo 'test';
CognitiveComplexity.php
<?php
declare(strict_types=1);
/**
* 認知的複雑度チェック
*/
function countEvenOdd(array $arr): array
{
// 修正:複雑度を下げるようリファクタリング
$evenCount = 0;
$oddCount = 0;
$totalOps = 0;
foreach ($arr as $value) {
$totalOps += pow($value, 3);
if ($value % 2 === 0) {
$evenCount++;
} else {
$oddCount++;
}
}
return ["even" => $evenCount, "odd" => $oddCount, "totalOps" => $totalOps];
}
この状態でもう一度vendor/bin/phpcs src/
を実行するとコーディング規約に非準拠の内容が出力されなくなります。
おわりに
PHP_Codesnifferは簡単に導入でき、今回使用したチェックルール以外にも様々なルールが用意されています。エラー内容によってはコードの自動修正も可能です。気になる方は公式のWikiをご参照ください。
実際の開発では静的解析ツールを併用して一定の品質を担保しつつ、コードレビューの負担を軽減するのに役立ちました。今後も改善しつつ運用を続けていきたいと思います。