目的
静的コード解析ツールのPHPMDの使用方法をまとめる。
What is PHPMD ?
PHPMDを使用すると、次の4つを静的に解析できる。
- 潜在的なバグ
- 準最適な状態のコード
- 複雑になっているコード
- 未使用となっているメソッド、プロパティ
環境
- Docker 20.10.12 / Docker Compose 1.29.2
- php 8.1.7
- phpmd/phpmd 2.12.0
- composer 2.3.7
- macOS Monterey 12.1 (M1チップ)
src(Docker環境下で/var/www/htmlと定義)
├── vendor
│ └──bin
│ └── phpmd
├── composer.json
├── composer.lock
├── sample.php
└── rulesets.xml
composer経由でPHPMDを導入
※下記では、すでにcomposerが導入され、composer.json、composer.lockファイルが存在していることを前提としました。
composer.jsonファイルに下記を記載し、ターミナルでupdateコマンドを実行する。
"require-dev": {
"phpmd/phpmd" : "@stable"
}
composer update phpmd/phpmd
※composer updateとしての実行も可能であるが(つまりphpmd/phpmdを書かない)、composer.jsonに記載されている全てが更新対象となり、意図しない部分のバージョンが更新されることも理解して使用する必要がある。
※composer install実行では何も起こらないので注意
(composer.lockファイルがある状況では、あくまでcomposer.lockファイルに記載のパッケージ情報をインストールするという意味になるため。
ちなみに下記公式ドキュメントにおいては、composerを初めて導入した後に導入する想定なので、composer install としての記述がなされている。
https://phpmd.org/download/index.html
)
実行コマンド
【形式】
phpmdまでのパス 解析対象ファイル・ディレクトリ 出力形式 使用するルール・ファイル名 [オプション]
【例】
<VSCode Remote Development環境下の場合>
./vendor/bin/phpmd . text unusedcode,naming --suffixes php --exclude vendor
<上記環境ではない場合>
docker compose exec app ./vendor/bin/phpmd . text unusedcode,naming --suffixes php --exclude vendor
【意味】
カレントディレクトリ以下の全ての.phpファイルを解析し、unusedcode,namingのルールに照らし合わせ、テキスト形式で結果を出力する(ただし、vendor以下ファイルは対象外とする)
コマンド末尾のオプション指定の例
オプション | 説明 | 使用例 |
---|---|---|
--reportfile | 結果を記載したファイルを新しく作成し出力する | --reportfile foo.xml |
--suffixes | 対象とするファイルの拡張子を指定する | --suffixes php |
--exclude | 除外するファイル、ディレクトリを指定 | --exclude vendor |
※--exclude vendor/*と指定するとエラーになるので、--exclude vendorが正と思われる。
その他のオプションは公式ドキュメントを参照
https://phpmd.org/documentation/index.html
ルールの例
ルール分類名 | 概要 | ルール例(一部抜粋) |
---|---|---|
cleancode | 綺麗なコードか | ElseExpression,StaticAccess |
codesize | 制御構造の数、メソッドやプロパティの数など | CyclomaticComplexity,TooManyMethods |
controversial | クラス、プロパティのCamelCase記法をチェック(賛否あり) | CamelCaseClassName,CamelCasePropertyName |
design | ソフトウェアデザイン(子クラスの数、非推奨構文など) | ExitExpression,NumberOfChildren |
naming | クラスやプロパティ名の長さなど命名規則のチェック | LongClassName,ShortVariable |
unusedcode | 未使用のプロパティやメソッド等のチェック | UnusedPrivateField,UnusedPrivateMethod |
詳細は公式ドキュメントを参照
https://phpmd.org/rules/index.html
結果の実例
1. <?php
2.
3. class Foo
4. {
5. public function bar()
6. { $sh = 'short test';
7. $longlonglonglongolonglong = 'long test';
8. }
9. }
※下記は全てVSCode Remote Development環境下での実行である
[実行コマンド]
/var/www/html# ./vendor/bin/phpmd sample.php text naming,unusedcode
ーーーーーーーーーーーーーーーー以下出力結果ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
/var/www/html/sample.php:6 ShortVariable Avoid variables with short names like $sh. Configured minimum length is 3.
→ 変数$shが2文字なので "ShortVariable" で検出(最低3文字以上が必要)
/var/www/html/sample.php:6 UnusedLocalVariable Avoid unused local variables such as '$sh'.
→ 変数$shが宣言後、未使用なので "UnusedLocalVariable" で検出
/var/www/html/sample.php:7 LongVariable Avoid excessively long variable names like $longlonglonglongolonglong. Keep variable name length under 20.
→ 変数$shが24文字なので "LongVariable" で検出(最大20文字をオーバー)
/var/www/html/sample.php:7 UnusedLocalVariable Avoid unused local variables such as '$longlonglonglongolonglong'.
→ 変数$longlonglonglongolonglongが宣言後、未使用なので "UnusedLocalVariable" で検出
ルールのカスタマイズ方法
githubのREADME.rstのCommand line usage項目内の While the rulesets.xml ruleset file could look like this:の部分をコピーしてくる。
→https://github.com/phpmd/phpmd
<rule />で囲まれた部分がルール部分であり、デフォルトでは6種類セットされている。
(既出の表で挙げたものである)
補足:この6種類のルールファイルは、下記ディレクトリに格納されている。
/var/www/html/vendor/phpmd/phpmd/src/main/resources/rulesets/
<?xml version="1.0"?>
<ruleset name="My first PHPMD rule set"
xmlns="http://pmd.sf.net/ruleset/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0
http://pmd.sf.net/ruleset_xml_schema.xsd"
xsi:noNamespaceSchemaLocation="
http://pmd.sf.net/ruleset_xml_schema.xsd">
<description>
My custom rule set that checks my code...
</description>
<rule ref="rulesets/codesize.xml" />
<rule ref="rulesets/cleancode.xml" />
<rule ref="rulesets/controversial.xml" />
<rule ref="rulesets/design.xml" />
<rule ref="rulesets/naming.xml" />
<rule ref="rulesets/unusedcode.xml" />
</ruleset>
必要に応じて<rule />タグに対して下記の編集を行う。
ルール分類にある一部のルールのみを適用する場合は、.xmlの後ろにルール名を追記する
<rule ref="rulesets/naming.xml/LongVariable" />
ルール分類にある一部のルールのみを除外する場合は、<exclude />タグでネストしてルール名を記載し、</rule>タグで閉じる
<rule ref="rulesets/naming.xml">
<exclude name="LongVariable" />
</rule>
参考 https://phpmd.org/documentation/creating-a-ruleset.html
検証ファイルそのものに除外ルールを記載する方法
コメントアウトの意味ではないので注意する。
またこれを記載した直下のクラスにだけ適用され、その後に出てくるクラスには適用されないようなので、有効範囲に注意が必要。(間違っていたらすみません)
全てのルールを除外
/**
* @SuppressWarnings(PHPMD)
*/
ある一部のルールを除外
/**
* @SuppressWarnings(PHPMD.LongVariable)
*/
参考 https://phpmd.org/documentation/suppress-warnings.html
参考
https://github.com/phpmd/phpmd
https://phpmd.org/
phpmdのルール一覧
PHPの静的コード解析ツール『PHPMD』を使ってみた。