PHP编码有很多工具,为我们带来很多便利,比如IDE、Debug工具,PHP单元测试工具等,对于CodeSniffer因为需要,有一定的研究,现在写出来,记录一下,以供以后需要。
工具简介
众所周知,统一的编码风格,不仅使你所写的代码清爽大气,也使无论是你本人,还是其他人,更容易阅读。那么一个统一的编码风格是怎么样的呢?他主要分为以 下几个方面,php标签、变量的命名、每一行的长度、缩进方式、控制语句以及函数的调用等等,具体的标准可以参考Expert PHP 5 Tools.pdf这本书的第一章,而对于我们团队来讲,也有自己的独有的风格,当前,Leapfrog中除了变量和函数命名方式与上书中第一章有所出入 外,其他的都是相同的。Leapfrog中使用的是下划线方式,zend一般采用驼峰方式。PHP_CodeSniffer能够自动检测你的源代码中的风 格为题,并给出具体的行号,告诉你这个与标准有什么出入,以提醒你改正。目前,该工具的安装环境是PHP version 5.1.2及以上。
工具的安装
使用 sudo pear install PHP_CodeSniffer-1.3.0 自动安装
工具的使用
Usage: phpcs [-nwlsapvi] [-d key[=value]]
[--report=] [--report-file= ] [--report- = ] ... [--report-width= ] [--generator= ] [--tab-width= ] [--severity= ] [--error-severity= ] [--warning-severity= ] [--config-set key value] [--config-delete key] [--config-show] [--standard= ] [--sniffs= ] [--encoding= ] [--extensions= ] [--ignore= ] ... -n Do not print warnings (shortcut for --warning-severity=0) -w Print both warnings and errors (on by default) -l Local directory only, no recursion -s Show sniff codes in all reports -a Run interactively -p Show progress of the run -v[v][v] Print verbose output -i Show a list of installed coding standards -d Set the [key] php.ini value to [value] or [true] if value is omitted --help Print this help message --version Print version information One or more files and/or directories to check A comma separated list of file extensions to check (only valid if checking a directory) A comma separated list of patterns to ignore files and directories The encoding of the files being checked (default is iso-8859-1) A comma separated list of sniff codes to limit the check to (all sniffs must be part of the specified standard) The minimum severity required to display an error or warning The name or path of the coding standard to use The number of spaces each tab represents The name of a doc generator to use (forces doc generation instead of checking) Print either the "full", "xml", "checkstyle", "csv", "emacs" "source", "summary", "svnblame" or "gitblame" report (the "full" report is printed by default) Write the report to the specified file path How many columns wide screen reports should be printed
主要介绍的是,-i参数,用来显示当前的检测风格,系统(1.3.0)默认了PEAR, MySource, Zend, PHPCS and Squiz几种风格
$ phpcs --report=summary /path/to/code 以汇总的方式,报告错误
$ phpcs --standard=PEAR /path/to/code/myfile.inc 指定以特定的标准检测
$ phpcs --extensions=php /path/to/code 仅仅检测php后缀文件
$ phpcs --config-set default_standard Squiz 设置默认值
忽略某些文件和文件夹的方法,有时候,我们要检测一个工程,但是呢,有时候因为文件太久,我们不想更改,而如果检测这些文件会带来很多问题这时候,我们可以选择忽略这些文件
$ phpcs --ignore=*/tests/*,*/data/* /path/to/code
所有的配置文件都写入了/home/renjun/php/lib/php/data/PHP_CodeSniffer/CodeSniffer.conf 因此要保证这个文件写权限,而且可以用vi进行编辑更改设置。 更多使用帮助请查看官方文档。
配置文件长什么样?
$phpCodeSnifferConfig = array ( 'default_standard' => 'Leapfrog', '--extensions' => 'php', '--ignore' => 'tools/,conf/config.inc.php', )
自定义风格
一般情况下,使用自带的几种风格就已经足够用,但是针对Leapfrog这种情况,我们需要一种自定义的方式来进行检测,否则,很多东西都要被报有问题,影响我们真正的寻找有问题的地方,而且很多时候,我们需要有一种自己的定义的风格方式,这就需要研究这个工具了。 要新建一个风格必须在/home/renjun/php/lib/php/PHP/CodeSniffer/Standards这样的路径下,依照已有的风格,建一个目录,目录中包含ruleset.xml和Sniffs目录。 前者是告诉系统,当前使用哪写检测规则,后者则是自定义过滤规则目录。打开ruleset.xml文件可以看到是这样的样子:
name:描述当前的检测标准的名称 description:描述信息 rule则是具体的检测规则,我们可以复用已有的规则,这样我们可以省去很多工作。 例如
class Generic_Sniffs_Functions_FunctionCallArgumentSpacingSniff implements PHP_CodeSniffer_Sniff {
public function register()
{
return array(T_STRING);
}
public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
{
$tokens = $phpcsFile->getTokens();
$tokens = $phpcsFile->getTokens();
$functionName = $stackPtr;
$ignoreTokens = PHP_CodeSniffer_Tokens::$emptyTokens;
$ignoreTokens[] = T_BITWISE_AND;
$functionKeyword = $phpcsFile->findPrevious($ignoreTokens, ($stackPtr - 1), null, true);
if ($tokens[$functionKeyword]['code'] === T_FUNCTION || $tokens[$functionKeyword]['code'] === T_CLASS) {
return;
}
$openBracket = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($functionName + 1), null, true);
if ($tokens[$openBracket]['code'] !== T_OPEN_PARENTHESIS) {
return;
}
$closeBracket = $tokens[$openBracket]['parenthesis_closer'];
$nextSeperator = $openBracket;
while (($nextSeperator = $phpcsFile->findNext(array(T_COMMA, T_VARIABLE), ($nextSeperator + 1), $closeBracket)) !== false) {
$brackets = $tokens[$nextSeperator]['nested_parenthesis'];
$lastBracket = array_pop($brackets);
if ($lastBracket !== $closeBracket) {
continue;
}
我只摘取一部分,详细的阅读官方文档。具体的,我们必须实现接口的具体方法,并且实现两个方法, public function register()、 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr),前者返回要处理的token。首先解释一下token,一个token是一个数组记录的是当前行的元素,例如,行号、这一行中的内 容,例如 : Array( [0] = > 367 [1] = >1 367是T_OPEN_TAG的值,表示php的开标签,而
其他功能
SVN Hook功能,可以在svn提交的时候进行检测,如果不符合标准,则不让通过。因为当前的Leapfrog比较复杂,难于严格的执行规则,可以在以后考虑。
检测部署
现在已经将检测的程序部署到了search041058.sqa.cm4机器上,适合Leapfrog风格,并且默认为使用Leapfrog进行检测,使用方法为 /home/renjun/php/bin/phpcs search.php 检测search.php文件 /home/renjun/php/bin/phpcs /home/renjun/leapfrog/ 检测目录 等等。。。。。 如果移植到其他机器上,只需要复制/home/renjun/php/lib/php/data/PHP_CodeSniffer/CodeSniffer.conf到相应的目录以及 /home/renjun/php/lib/php/PHP/CodeSniffer/Standards/Leapfrog/目录到特定目录。
参考资料
http://pear.php.net/manual/en/package.php.php-codesniffer.config-options.php
Expert PHP 5 Tools.pdf