PHPのソース解析用の便利な検証ツール導入

概要

PHPでの開発は行なっているけどソースの品質を向上させるためのアプローチがけっこう停滞している。

unoh.github.com by unohを参考にさせてもらって
そのためのソースに対して解析を行えるツールを試しに利用してみる。

環境

試した環境は、さくらのVPSで
OSは、CentOS v5.5。
phpは、v5.3.8。
Apacheは、 v2.2.21。

導入してみたツール

phpcpd

sebastianbergmann/phpcpd · GitHub
コードの中でコピー&ペーストで記述されている部分の検出してくれるツール。

phpdcd

sebastianbergmann/phpdcd · GitHub
どこからもコールされていないファンクションが無いかをチェックするためのツール

phploc

sebastianbergmann/phploc · GitHub
phpのファイル構成を調べてくれるツール

phpmd

PHPMD - PHP Mess Detector
バグの可能性になりそうなコード、最適化できそうなコード、複雑すぎる記述になっているコード、使われていないファンクション・パラメータ、を検出してくれるツール。Jenkinsのpluginとしても動作できる。(Javafindbugsのような位置付け)

インストール方法・実行方法などなど

  • phpcpd

さっそくインストールしてみる。インストール方法はPEAR経由で簡単にできる。


[naoki@www22404u ~]$ php -v
PHP 5.3.8 (cli) (built: Sep 30 2011 20:07:13)
Copyright (c) 1997-2011 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2011 Zend Technologies
with Xdebug v2.1.1, Copyright (c) 2002-2011, by Derick Rethans

[naoki@www22404u ~]$ sudo pear config-set auto_discover 1
config-set succeeded

[naoki@www22404u ~]$ sudo pear install pear.phpunit.de/phpcpd
Attempting to discover channel "pear.phpunit.de"...
downloading channel.xml ...
Starting to download channel.xml (804 bytes)
....done: 804 bytes
Auto-discovered channel "pear.phpunit.de", alias "phpunit", adding to registry
Attempting to discover channel "components.ez.no"...
downloading channel.xml ...
Starting to download channel.xml (591 bytes)
...done: 591 bytes
Auto-discovered channel "components.ez.no", alias "ezc", adding to registry
phpunit/phpcpd requires PEAR Installer (version >= 1.9.4), installed version is 1.9.2
downloading File_Iterator-1.3.1.tgz ...
Starting to download File_Iterator-1.3.1.tgz (5,157 bytes)
...done: 5,157 bytes
downloading PHP_Timer-1.0.2.tgz ...
Starting to download PHP_Timer-1.0.2.tgz (3,686 bytes)
...done: 3,686 bytes
downloading ConsoleTools-1.6.1.tgz ...
Starting to download ConsoleTools-1.6.1.tgz (869,994 bytes)
...done: 869,994 bytes
downloading Base-1.8.tgz ...
Starting to download Base-1.8.tgz (236,357 bytes)
...done: 236,357 bytes
install ok: channel://pear.phpunit.de/File_Iterator-1.3.1
install ok: channel://pear.phpunit.de/PHP_Timer-1.0.2
install ok: channel://components.ez.no/Base-1.8
install ok: channel://components.ez.no/ConsoleTools-1.6.1

pear のバージョンがv1.9.4より古かったので、pear自体のupgradeを実施。


[naoki@www22404u ~]$ sudo pear upgrade pear
WARNING: channel "pear.php.net" has updated its protocols, use "pear channel-update pear.php.net" to update
downloading PEAR-1.9.4.tgz ...
Starting to download PEAR-1.9.4.tgz (296,332 bytes)
.............................................................done: 296,332 bytes
downloading Archive_Tar-1.3.8.tgz ...
Starting to download Archive_Tar-1.3.8.tgz (17,995 bytes)
...done: 17,995 bytes
upgrade ok: channel://pear.php.net/Archive_Tar-1.3.8
upgrade ok: channel://pear.php.net/PEAR-1.9.4
PEAR: Optional feature webinstaller available (PEAR's web-based installer)
PEAR: Optional feature gtkinstaller available (PEAR's PHP-GTK-based installer)
PEAR: Optional feature gtk2installer available (PEAR's PHP-GTK2-based installer)
PEAR: To install optional features use "pear install pear/PEAR#featurename"

[naoki@www22404u ~]$ sudo pear config-set auto_discover 1
config-set succeeded

[naoki@www22404u ~]$ sudo pear install pear.phpunit.de/phpcpd
downloading phpcpd-1.3.5.tgz ...
Starting to download phpcpd-1.3.5.tgz (8,746 bytes)
.....done: 8,746 bytes
install ok: channel://pear.phpunit.de/phpcpd-1.3.5 ※今度は、phpcpd v1.3.5のインストールできた。

利用方法は phpcpd [directory/path]。
今回は、index.phpという全く同じ記述をしたソースファイルを、index_cp.phpとして用意した。


[naoki@www22404u php_sandbox]$ ll /home/naoki/src/php_sandbox/
-rw-rw-r-- 1 naoki naoki 3599 11月 27 04:24 index.php
-rw-rw-r-- 1 naoki naoki 3599 2月 5 14:29 index_cp.php

[naoki@www22404u php_sandbox]$ phpcpd /home/naoki/src/php_sandbox/
phpcpd 1.3.5 by Sebastian Bergmann.

Found 1 exact clones with 15 duplicated lines in 2 files:

- /index.php:67-82
/index_cp.php:67-82

3.62% duplicated lines out of 414 total lines of code.

Time: 0 seconds, Memory: 2.50Mb

  • phpdcd

インストール方法はpear経由。


[naoki@www22404u ~]$ sudo pear config-set auto_discover 1
config-set succeeded

[naoki@www22404u ~]$ sudo pear install pear.phpunit.de/phpdcd
Failed to download phpunit/phpdcd within preferred state "stable", latest release is version 0.9.3, stability "beta", use "channel://pear.phpunit.de/phpdcd-0.9.3" to install
install failed


最新だとstableじゃないからダメだって。stable版のv.0.9.3を利用してみる。


[naoki@www22404u ~]$ sudo pear install pear.phpunit.de/phpdcd-0.9.3
downloading phpdcd-0.9.3.tgz ...
Starting to download phpdcd-0.9.3.tgz (5,827 bytes)
.....done: 5,827 bytes
downloading PHP_TokenStream-1.1.2.tgz ...
Starting to download PHP_TokenStream-1.1.2.tgz (9,797 bytes)
...done: 9,797 bytes
install ok: channel://pear.phpunit.de/PHP_TokenStream-1.1.2
install ok: channel://pear.phpunit.de/phpdcd-0.9.3

これで準備完了。

利用方法は、第1引数に対象のソースがおいてあるディレクトリを指定してあげるだけ。
実行結果はこんな感じ。isIncluderメソッドがどこからもコールされていないことが分かる。


[naoki@www22404u ~]$ ll /home/naoki/src/php_sandbox/
-rw-rw-r-- 1 naoki naoki 1239 11月 27 04:24 geoIndex.php
-rw-rw-r-- 1 naoki naoki 2375 11月 27 04:24 geoSample2.php
-rw-rw-r-- 1 naoki naoki 691 11月 27 04:24 googleMaps.php
-rw-rw-r-- 1 naoki naoki 3599 11月 27 04:24 index.php
-rw-rw-r-- 1 naoki naoki 3599 2月 5 14:29 index_cp.php
-rw-rw-r-- 1 naoki naoki 609 10月 29 17:20 test.php
-rw-rw-r-- 1 naoki naoki 1857 11月 27 04:24 tweet.php

[naoki@www22404u ~]$ phpdcd /home/naoki/src/php_sandbox/
phpdcd 0.9.3 by Sebastian Bergmann.

- isIncludedUrl()
declared in /tweet.php:53

Time: 0 seconds, Memory: 4.50Mb

  • phploc

インストールはpear経由で。ほんと簡単。


[naoki@www22404u ~]$ sudo pear config-set auto_discover 1
config-set succeeded

[naoki@www22404u ~]$ sudo pear install pear.phpunit.de/phploc
phpunit/phploc can optionally use PHP extension "bytekit"
downloading phploc-1.6.4.tgz ...
Starting to download phploc-1.6.4.tgz (8,481 bytes)
.....done: 8,481 bytes
install ok: channel://pear.phpunit.de/phploc-1.6.4


実行方法は、上のツールと同じ。
実行すると、php内部の構成が解析されて数値として確認することができる。

[naoki@www22404u ~]$ ll /home/naoki/src/php_sandbox/
-rw-rw-r-- 1 naoki naoki 1239 11月 27 04:24 geoIndex.php
-rw-rw-r-- 1 naoki naoki 2375 11月 27 04:24 geoSample2.php
-rw-rw-r-- 1 naoki naoki 691 11月 27 04:24 googleMaps.php
-rw-rw-r-- 1 naoki naoki 3599 11月 27 04:24 index.php
-rw-rw-r-- 1 naoki naoki 3599 2月 5 14:29 index_cp.php
-rw-rw-r-- 1 naoki naoki 609 10月 29 17:20 test.php
-rw-rw-r-- 1 naoki naoki 1857 11月 27 04:24 tweet.php

[naoki@www22404u ~]$ phploc /home/naoki/src/php_sandbox/
phploc 1.6.4 by Sebastian Bergmann.

Lines of Code (LOC): 414
Cyclomatic Complexity / Lines of Code: 0.04
Comment Lines of Code (CLOC): 4
Non-Comment Lines of Code (NCLOC): 410

Namespaces: 0
Interfaces: 0
Classes: 1
Abstract: 0 (0.00%)
Concrete: 1 (100.00%)
Average Class Length (NCLOC): 33
Methods: 2
Scope:
Non-Static: 2 (100.00%)
Static: 0 (0.00%)
Visibility:
Public: 1 (50.00%)
Non-Public: 1 (50.00%)
Average Method Length (NCLOC): 16
Cyclomatic Complexity / Number of Methods: 3.50

Anonymous Functions: 0
Functions: 3

Constants: 0
Global constants: 0
Class constants: 0

  • phpmd

インストールは、pear経由でこれもOK。


[naoki@www22404u ~]$ sudo pear channel-discover pear.phpmd.org
Adding Channel "pear.phpmd.org" succeeded
Discovery of channel "pear.phpmd.org" succeeded

[naoki@www22404u ~]$ sudo pear channel-discover pear.pdepend.org
Adding Channel "pear.pdepend.org" succeeded
Discovery of channel "pear.pdepend.org" succeeded

[naoki@www22404u ~]$ sudo pear install --alldeps phpmd/PHP_PMD
downloading PHP_PMD-1.3.0.tgz ...
Starting to download PHP_PMD-1.3.0.tgz (45,722 bytes)
.............done: 45,722 bytes
downloading PHP_Depend-1.0.0.tgz ...
Starting to download PHP_Depend-1.0.0.tgz (180,666 bytes)
...done: 180,666 bytes
downloading imagick-3.0.1.tgz ...
Starting to download imagick-3.0.1.tgz (93,920 bytes)
...done: 93,920 bytes
install ok: channel://pear.pdepend.org/PHP_Depend-1.0.0
13 source files, building
running: phpize
Configuring for:
PHP Api Version: 20090626
Zend Module Api No: 20090626
Zend Extension Api No: 220090626
Please provide the prefix of Imagemagick installation [autodetect] : y
building in /var/tmp/pear-build-rootIOlddC/imagick-3.0.1
running: /var/tmp/imagick/configure --with-imagick=y
checking for egrep... grep -E
checking for a sed that does not truncate output... /bin/sed
checking for cc... cc
checking for C compiler default output file name... a.out
checking whether the C compiler works... yes
checking whether we are cross compiling... no
checking for suffix of executables...
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether cc accepts -g... yes
checking for cc option to accept ANSI C... none needed
checking how to run the C preprocessor... cc -E
checking for icc... no
checking for suncc... no
checking whether cc understands -c and -o together... yes
checking for system library directory... lib
checking if compiler supports -R... no
checking if compiler supports -Wl,-rpath,... yes
checking build system type... x86_64-redhat-linux-gnu
checking host system type... x86_64-redhat-linux-gnu
checking target system type... x86_64-redhat-linux-gnu
checking for PHP prefix... /usr
checking for PHP includes... -I/usr/include/php -I/usr/include/php/main -I/usr/include/php/TSRM -I/usr/include/php/Zend -I/usr/include/php/ext -I/usr/include/php/ext/date/lib
checking for PHP extension directory... /usr/lib64/php/modules
checking for PHP installed headers prefix... /usr/include/php
checking if debug is enabled... no
checking if zts is enabled... no
checking for re2c... no
configure: WARNING: You will need re2c 0.13.4 or later if you want to regenerate PHP parsers.
checking for gawk... gawk
checking whether to enable the imagick extension... yes, shared
checking whether to enable the imagick GraphicsMagick backend... no
checking ImageMagick MagickWand API configuration program... configure: error: not found. Please provide a path to MagickWand-config or Wand-config program.
ERROR: `/var/tmp/imagick/configure --with-imagick=y' failed
install ok: channel://pear.phpmd.org/PHP_PMD-1.3.0


早速、実行してみる。実行方法は、
> phpmd [filename|directory] [report format] [ruleset file], i.e:

ルールセットは、カスタマイズ可能だが、今回はもともと用意されてあるルールセットで
解析を実行してみた。codesize, unusedcode,namingを指定。
まずはtext形式で実行してみる。


[naoki@www22404u ~]$ phpmd /home/naoki/src/php_sandbox/ text codesize,unusedcode,naming

/home/naoki/src/php_sandbox/geoIndex.php:33 Avoid variables with short names like $i. Configured minimum length is 3.


実行結果としては、変数$iが短すぎるよって解析結果が、text形式かxml形式で出力される。
結構効率よく、コードの静的な解析ができて便利!!
xml形式に指定も可能。

[naoki@www22404u ~]$ phpmd /home/naoki/src/php_sandbox/ xml codesize,unusedcode,naming




Avoid variables with short names like $i. Configured minimum length is 3.

まとめ

これらのツールを活用してコードの中身をもっと、リファクタリングしていったり、
品質あげるアプローチをしていきたいと思う。
phpunitについては、まだ未導入であるため、今度はphpunitを利用してあわせて
リファクタリング・TDDの導入をやっていきたいところ。