LoginSignup
1
0

More than 1 year has passed since last update.

静的コード解析ツールのPHPMDを導入した話

Last updated at Posted at 2022-07-03

目的

静的コード解析ツールの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コマンドを実行する。

composer.json
    "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

結果の実例

sample.php(解析対象ファイル)

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/

rulesets.xml(githubからそのままコピー)
<?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 />タグに対して下記の編集を行う。

上記rulesets.xmlを編集
ルール分類にある一部のルールのみを適用する場合は、.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

検証ファイルそのものに除外ルールを記載する方法

コメントアウトの意味ではないので注意する。
またこれを記載した直下のクラスにだけ適用され、その後に出てくるクラスには適用されないようなので、有効範囲に注意が必要。(間違っていたらすみません)

任意の.phpファイル
全てのルールを除外
/**
* @SuppressWarnings(PHPMD)
 */

ある一部のルールを除外
/**
* @SuppressWarnings(PHPMD.LongVariable)
 */

参考 https://phpmd.org/documentation/suppress-warnings.html

参考

https://github.com/phpmd/phpmd
https://phpmd.org/
phpmdのルール一覧
PHPの静的コード解析ツール『PHPMD』を使ってみた。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0