PHPの開発環境を構築する(その5): PHPMDを試す

「PHPの開発環境を構築する」シリーズの第5回です。今回は、オープンソースでPHP用の静的解析ツールである、PHPMDを試してみます。PHPMDによる使われていない変数の警告によって、変数名のタイプミスが発見できそうです。

順番を入れ替え、最初にPHPMDの試用レビューをし、その後でインストールをレポートします。

(2014年12月23日追記:インストール時の「謎のエラー」を無視しても、動作することを確認しました。またWindows 8.1の場合に付いて追記しました。)

(2015年2月26日追記:インストール方法については「Composerによるツールのインストール」を起稿しました。こちらをご参照下さい。)

はじめに

PHPは、柔軟で便利なツールもそろっている、プログラミングがしやすい言語です。

しかし一点、変数が無宣言で使えるので、タイプミスによる欠陥を作りこみやすいです。またインタプリタ型なので実行してみないと欠陥がわかりません。

そこで静的解析ツールを試してみようと思いました。

PHPMDはオープンソースの静的解析ツールです。PMDというJavaのツールがもとになっているようです。(Javaプログラミングの予定はありません。しかしPMDはJavascriptの解析もできるようですので、将来お試しするかもしれません。)

尚、本稿は以下の環境をもとに記載しております。

  • Windows7 64bit
  • PHP 5.4.7 (VC9 X86 32bit thread safe) +PEAR : C:\pleiades\xampp\php\php.exe

(2014年12月23日追記:Windows 8.1+php 5.4.19+PEARで動作確認しました。)

記事中のPHPのバージョンやパス等は各位の環境に合わせて読み替え、適切なパッケージのインストールと設定をお願いいたします。

PHPMD

PHPMDのページは以下になります。

http://phpmd.org/

本稿の時点でのPHPMDのバージョンは、PHPMD 1.5.0です。

PHPMDの試用レビュー

PHPMDは、読まれる方にとって必ずしも必要なツールとは思えません。(とは言え検索でお越しになった方は興味を持っていると思います。)

そこで普段はインストールからレポートするのですが、順番を入れ替えて、使ってみてのレビューより書こうと思います。インストールは次の章でレポートします。

PHPMDの使い方

–helpオプションで使い方を確認します。

C:\skydrive\workspace >C:\pleiades\xampp\php\phpmd.bat --help
Mandatory arguments:
1) A php source code filename or directory. Can be a comma-separated string
2) A report format
3) A ruleset filename or a comma-separated string of rulesetfilenames

Available formats: xml, text, html.
Available rulesets: cleancode, codesize, controversial, design, naming, unusedcode.

Optional arguments that may be put after the mandatory arguments:
--minimumpriority: rule priority threshold; rules with lower priority than thiswill not be used
--reportfile: send report output to a file; default to STDOUT
--suffixes: comma-separated string of valid source code filename extensions
--exclude: comma-separated string of patterns that are used to ignore directories
--strict: also report those nodes with a @SuppressWarnings annotation

とりあえず、プリセットされているルールセットによってレポートを作成するバッチファイルを作成しました。

md.bat

FOR %%r IN (cleancode codesize controversial design naming unusedcode) DO ^
C:\pleiades\xampp\php\phpmd.bat --reportfile docs\metrics\%%r.html src html %%r

これをプロジェクトのルートに置きます。srcはソースファイルを置いているディレクトリ、docs\metricsがレポートを格納するディレクトリです。

最後のhtmlをxmlやtextに変えると対応したファイルが作成されますが、試してみたところhtmlだけで十分のように思います。

またルールセットをコンマ区切りでいっぺんに指定することもできます。

しかしレポートを見ると、どのルールセットによってなされた警告なのかわからないので、最初は上記バッチファイルのように別々に生成してみることをお勧めします。

バッチファイルを実行すると、以下の様なレポートがルールセットごとに生成されます。

PHPMDのHTMLレポート

PHPMDによる警告

本節では、私のコードに対して実際にPHPMDが出力した警告(Problem)を、ルールセットごとに示します。それらを評価した上で使い方を考えたいと思います。

出力される警告の傾向は、人あるいは組織によって異なると思います。またPHPMDのバージョンによっても異なりますので、できれば実際に自身のコードを解析してみてください。

またさらに詳しくはPHPMDのサイトのルールのページをご参照ください。

cleancode

cleancodeによって出力された警告は以下です。

  • The method メソッド名 uses an else expression. Else is never necessary and you can simplify the code to work without else.
  • Avoid using static access to class ‘クラス名’ in method ‘メソッド名’.
  • The method メソッド名 has a boolean flag argument $変数名, which is a certain sign of a Single Responsibility Principle violation.

一点目は「Elseを使わずにコードをシンプルにしましょう」と言っています。Elseブロックが変数値の設定程度であれば仰ることはわかるのですが、実際のコードを見ると関数コールなどでElseブロックは必要です。

二点目は「メソッドに対して$obj->Method();以外のアクセスはするな」と言っています。しかしその個所はメソッドコールではなく、定数(const)の参照やnewによるインスタンスの生成です。

三点目は「booleanの引数はSingle Responsibility Principle違反!」らしいです。PHPMDは引数にスイッチを付けるのはお気に召さないようです。

以上より、私はcleancodeは必要ないと判断しました。

しかしこれらのルールは先に示したルールのページに解説はなく、比較的新しいルールセットだと推測できます。将来はより洗練されるかもしれません。

codesize

codesizeによって出力された警告は以下です。

  • The class クラス名 has an overall complexity of 数値 which is very high. The configured complexity threshold is 50.
  • The method メソッド名 has a Cyclomatic Complexity of 数値. The configured cyclomatic complexity threshold is 10.

いずれも複雑度(サイクロマティック複雑度)についてのものです。まあ評価としてはあってもいいかなと思います。(サイクロマティック複雑度はPHPUnitでも計測できます。)

controversial

controversialによって出力された警告は以下です。

  • The property $プロパティ名 is not named in camelCase.
  • The parameter $引数名 is not named in camelCase.
  • The variable $変数名 is not named in camelCase.
  • The method メソッド名 is not named in camelCase.
  • The class クラス名 is not named in CamelCase.
  • メソッド名accesses the super-global variable $スーパーグローバル変数名.

最後の一点を除き、コーディング標準の命名規約に関するものです。しかし私はPHPMDお勧め(Java流)の命名規約に従ってはいません。

また最後の一点は、必要に応じてスーパーグローバルも参照するだろうよ、ということで必要ありません。

結論としてcontroversialは必要ありません。

design

designによって出力された警告は以下です。

  • The function 関数名 contains an exit expression.
  • The function 関数名 contains an eval expression.

上記の警告が出ているファイルはスクリプト的なファイルなので関数内でexit及びevalを使っていますが、通常は使わないでしょう。

設計についてのルールはあったほうが良いので、使ってみようと思います。

naming

namingによって出力された警告は以下です。

  • Avoid variables with short names like $変数名. Configured minimum length is 3.

短い変数名ですが、ループカウンタについてはこの警告は出ないようです。

その他、短い名前や「booleanが返り値ならgetX()でなくてisX()、hasX()にしろ」みたいな警告もあるようです。

こちらの名付けについては、ごもっともなので使うことにします。

unusedcode

unusedcodeによって出力された警告は以下です。

  • Avoid unused local variables such as ‘$変数名’.
  • Avoid unused private methods such as ‘メソッド名’.

使われていない変数やprivateメソッドというのは、タイプミスの可能性が高いです。実際に一点目はそうでした。

二点目はpreg_replace_callbackのコールバック関数として使っているメソッドに対して出力されました。そこまでは解析していないようですね。

欠陥の検出に役立ちそうなので使います。

PHPMDの使い方まとめ

以上により、私は以下の様にPHPMDを使ってみようと思います。

  • codesizeによるレポート : 修正対象としてではなく、評価として眺める。
  • design, naming, unusedcodeによるレポート : 警告は修正対象とする。
  • 文法上の誤りがあるとパースエラーが発生するので、テスト実行前にかけるとよいかも。(コンパイルの代わり。しかしEclipse+PDTが既に吸収してくれているかも。)

(ルールの自作はしません。キッパリ。)

2つのレポート生成を、PHPでスクリプト風に書くと以下の様になります。

$s_phpmd = 'C:/Pleiades/xampp/php/phpmd.bat';
$s_src_dir = 'src';
$s_report_dir = 'docs/metrics';
exec( "$s_phpmd  --reportfile $s_report_dir/complexity.html $s_src_dir html codesize");
exec( "$s_phpmd  --reportfile $s_report_dir/correctable.html $s_src_dir html design,naming,unusedcode");

将来は開発ツールに組み込んで、Eclipseの外部ツールに設定することになると思います。

また修正対象のレポートにも修正しない項目が警告されることはありえます。その場合はphpdocコメントに、@SuppressWarnings(PHPMD.UnusedLocalVariable)のように書けば警告を抑えられるようですので、使ってみようと思います。

インストール

<2015年2月26日追記:Composerによるインストール>

以降に記述のPearによるインストールは、現在サポートされていないようです。

新しく「Composerによるツールのインストール」を書きましたので、こちらをご参照下さい。

以降の記述は残しておきますが、追試しても最新版はインストールできません。

</2015年2月26日追記>

PHPMDのインストール作業をレポートします。本章では私が行った作業を示しますが、途中でエラーが発生し、結局何が最適か分かっていません。

中途半端なレポートですが、幾分かの参考になれば幸いです。または私と異なる環境やバージョンによっては、エラーが発生しないことも考えられます。

インストールにはPEARを使いましたが、その他のインストール法についてはPHPMDのダウンロードの解説ページをご参照ください。

PHPMDのインストール

コマンドプロンプトより、以下を入力しPHPMDをインストールします。

(2014年12月23日追記:Windows 8.1では、管理者モードのコマンドプロンプト(Windowsキー+X→A)で入力します。)

C:\Users\user>cd C:\pleiades\xampp\php
C:\pleiades\xampp\php>pear.bat channel-discover pear.phpmd.org
C:\pleiades\xampp\php>pear.bat channel-discover pear.pdepend.org
C:\pleiades\xampp\php>pear.bat install --alldeps phpmd/PHP_PMD

(2014年12月23日追記:以降に記述の「謎のエラー」を無視しても、動作することを確認しました。)

これでインストールが成功するとよいのですが、以下の様なエラーが発生しました(謎1)。

WARNING: php_bin C:\pleiades\xampp\php\.\php.exe appears to have a suffix \.\php.exe, but config variable php_suffix does not match
ERROR: The DSP imagick.dsp does not exist.
install ok: channel://pear.phpmd.org/PHP_PMD-1.5.0

phpフォルダの中にはphpmdができていますので、最終的には成功しているようです。しかしimagickの構築に失敗しているようです。「ImageMagickはインストールしていないので、さもありなん」とも思いました。

このときはPHPMDがコードを解析してdoxigenのように絵を書いてくれるのかな、と考えていました。しかし前述のように、PHPMDを動作させても絵を書いてくれる様子はありませんので、ImageMagicは必要ないのかもしれません。

ということで私はこの時点でImageMagickをインストールすることにしました。しかし必要ない作業かもしれませんので、以下の節は飛ばして、とりあえずPHPMDを実行してみてください。

ImageMagickのインストール

ImageMagickのサイトダウンロードページからバイナリがダウンロードできます。

私の環境はWindows7の64bitなのでImageMagick-6.8.7-8-Q16-x64-dll.exeで良いはずなのですが、後に書きますphp_imagick.dllをPHPに読み込ませる際にエラーが発生しました(謎2)。試行錯誤した結果32bit版のImageMagick-6.8.7-8-Q16-x86-dll.exeをインストールしました。

ダウンロードしたインストーラーを実行すると、普通にインストールが終了します。途中で設定を聞かれますが、ディスクトップにアイコンを作成する旨のチェックを外したくらいです。

php_imagick.dllのインストール

その後「pecl install imagick」のとしてimagickのインストールを試みましたが、最初と同じエラーが発生しました(謎3)。

peclのパッケージのページをみると、PHP5.4かつWindows64bit対応のパッケージはありません。(このためエラーが発生していたのかもしれません。) 私はここから、「5.4 Thread Safe (TS) x86」をクリックしてパッケージをダウンロードしました。各位におきましてはPHPのバージョン等を確認して適切なパッケージをダウンロードしてください。

zipを解凍すると、php_imagick.dllがありますので、これをC:\pleiades\xampp\php\extにコピーします。

残りのCORE_RLで始まるdllはVC9の再頒布可能dllですので、マイクロソクト配布のインストーラーを使うことにします。マイクロソフトのダウンロードページよりダウンロードしたインストーラーを実行することで、これらのdllのインストールは終了します。

念のため、ここでPCを再起動したほうが良いかもしれません。

php.iniの編集

php.ini(C:\pleiades\xampp\php\php.ini)をテキストエディタで開きます。

「extension=」の記述が固まっているブロックがありますので、その最後辺りに以下の一行を追記します。

extension=php_imagick.dll

imagickの確認

コマンドプロンプトより、以下の様に入力すると、imagickが正しくインストールされていることが確認できます。

C:\Users\user>cd C:\pleiades\xampp\php
C:\pleiades\xampp\php>php -i | findstr "imagick"
imagick
imagick module => enabled
imagick module version => 3.1.2
imagick classes => Imagick, ImagickDraw, ImagickPixel, ImagickPixelIterator
imagick.locale_fix => 0 => 0
imagick.progress_monitor => 0 => 0

PHPMDの再インストール

続いてPHPMDを再インストールします。

C:\pleiades\xampp\php>pear.bat uninstall phpmd/PHP_PMD
C:\pleiades\xampp\php>pear clear-cache
C:\pleiades\xampp\php>pear.bat install phpmd/PHP_PMD

2行は必要ないかもしれません。飛ばして3行を打ち込み、エラーが出るようでしたら試してください。

以上、私がPHPMDのインストールの際に行った作業です。

まとめ

PHP用の静的解析ツールであるPHPMDをインストールしました。途中で謎のエラーが発生しましたが、現在のところPHPMDは動作しています。

実際にレポートを作成させてみると、いらないルールと使えそうなルールが混じっています。私にとっては有用そうなので使ってみようと思います。(特に、使われていない変数の警告で欠陥が発見できそうです。)

現在、PHPUnitやPHPDocumentorをランチしてレポートを生成するツールを作成中です。そこにPHPMDのランチャも追加して、次回あたりにお知らせできればと思います。

One thought on “PHPの開発環境を構築する(その5): PHPMDを試す

  1. Pingback: コード解析ツールまとめ(PHPMD,Cppcheck) – simple it life

コメントを残す