PHP语法检查前源代码控制

33

参考是否有像Lint那样的PHP文件静态代码分析器?--我正在寻找如何在开发人员提交代码之前评估PHP文件的内容。无论哪种解决方案都将通过类似于答案的SVN钩子触发:是否可能从PHP检查PHP文件语法?

我找到了这个将PHP文件自动语法检查到SVN中的方法,这正是我要追求的方向,但是...php -l并不足够。

例如,给定以下代码:

if ($foo == 'bar') { 
     echo $foo;
}

这导致:

2012/01/15 02:51:14 [error] 694#0: *164 FastCGI在stderr中发送的内容为:"PHP Notice: Undefined variable: foo

与之相比:

if (isset($foo)) { echo $foo; }
一些问题需要通过教育程序员的最佳实践来解决。不幸的是,有些人学习速度没有其他人快,确保遵守编码标准的唯一方式是减少未经测试或不符合标准的内容输入到SVN中。

从这个问题的第一个链接中,我尝试过:

    if ($foo == 'bar') {
                     \_ HERE

==== /mnt/hgfs/workspace/scratch-pad/phpinfo.php:44: 警告: comparing (unknown) == (string): 无法检查未知类型之间的比较

它们各有所长,但都没有捕获这些只在运行时才会出现的问题。

欢迎就此主题提供意见和想法。

编辑

有一位发布者建议使用PHPLint,我想,好吧!考虑到有一个新版本:phplint-pure-c-1.1_20120202

 <?php
 if ($foo == 'bar') {
     echo $foo;
 }
 ?>

简单测试....................,它有效,并且报告了1个错误和1个警告。但是,如果在if语句之前添加以下内容:

 <?php
 if (isset($foo) && $foo == 'bar') { echo 'man'; }
 if ($foo == 'bar') { 
     echo $foo;
 }
 ?>

它不起作用,并且报告0个错误,2个警告。


8
让他们写单元测试吧。语法检查无法找出大部分错误,而单元测试可以。 - NikiC
6
在 SVN 的 pre-commit hook 中做这种事情要非常小心。实际上我会毫不犹豫地说不要这样做。除非提交被拒绝,否则你看不到 svn pre-commit hook 的输出 - 当你基于非关键错误阻止提交时,这可能会产生极大的干扰。除非你将符合性视为高于生产力,否则最好在开发者的机器上实施此类检查。如果你使用 svn,则更适合将其与构建系统集成。 - AD7six
总会有一些情况不如你所愿。但这并不改变 phplint 最初执行你要求的事实。请注意,我并没有说你应该使用它 - 我只是暗示它符合你提出的要求。 - eis
@eis 我知道。感谢你的努力和回复...这是一堆糟糕解决方案中最好的一个 :) - sdolgy
我同意@AD7six的观点。将其与构建系统绑定将使开发人员的体验更加愉快,并且配置也会更容易。 - A.J. Brown
6个回答

11

我认为对于分析器来说,这可能有些困难,你提供的代码可能会在使用register_globals的帮助下运行。此外,它可能被定义在包含此文件的某个其他文件中。出于这些原因,PHP文件应该在完整上下文的其他文件的情况下进行分析,这样才能真正可靠,并且应将PHP/server配置提供给或者定义到分析机制中。

话虽如此,你确定phplint不能满足你的需求吗?

这里有一个在线验证器,你可以用来测试它。给定输入:

<?php

echo $foo;

结果是:

        echo $foo;
                  \_ HERE
==== 3: ERROR: variable `$foo' has not been assigned
END parsing of test-qBlPWw
==== ?: notice: unused package `dummy.php'
==== ?: notice: unused module `standard'
Overall test results: 1 errors, 0 warnings.

相较于isset(),它没有发现任何问题。

编辑:所以对于这个其他的测试案例:

<?php

if ($foo == 'bar') echo $foo;

在 Linux Mint 8 上,响应是:

$ src/phplint test.php 
/home/vadmin/phplint/phplint-pure-c-1.0_20110223/test.php:3: ERROR: variable `$foo' has not been assigned
/home/vadmin/phplint/phplint-pure-c-1.0_20110223/test.php:3: Warning: comparing (unknown) == (string): cannot check the comparison between unknown types
Overall test results: 1 errors, 1 warnings.

而且使用这个:

<?php

$foo = '1';
if ($foo == 1) echo $foo;

它是:

$ src/phplint test.php 
/home/vadmin/phplint/phplint-pure-c-1.0_20110223/test.php:6: ERROR: comparing (string) == (int)
Overall test results: 1 errors, 0 warnings.

那它不应该像应该的那样工作,然后正确地报告问题吗?


嗨,我没有使用在线验证器,因为我们不会将代码发送到组织之外的网络...我下载并编译了PHPLint代码,并在本地运行,但没有返回你所展示的结果。 - sdolgy
编译 phplint-pure-c-1.0_20110223 在 Linux 上得到了不同的结果。太棒了。 - sdolgy
有趣。我也在Mint 8和phplint-pure-c-1.0_20110223上进行了测试,并得到了相同的结果: echo $foo; \_ 这里==== /home/vadmin/phplint/phplint-pure-c-1.0_20110223/test.php:3: 错误: 变量 `$foo' 没有被赋值 总体测试结果: 1个错误,0个警告。 子进程异常退出,代码为1。 - eis
哦,我明白了,你现在改变了测试用例。所以说,对于这个新的测试用例,它不起作用,但是对于最初在问题中提到的那个测试用例,它可以工作? - eis
@sdolgy:已将新的测试用例添加到答案中。 - eis
显示剩余2条评论

8
你可能希望结合使用phpcs(遵守编码规范)和Sebastian Bergmann的新项目:https://github.com/sebastianbergmann/hphpa。这个项目利用Facebook的静态编译器来检查错误,比如你所寻找的...作为预提交钩子可能有些过度,但是钩入你的构建系统可能就足够了。

5

所有这些智能的超级工具都可以偷听每扇门和窥视每个锁孔,但它们永远无法与运行代码的愚蠢和直接的行为相提并论。

在repo中拥有可编译的、语法正确的php文件有什么价值呢?你可以制造大量这样的文件,并定期提交到repo中,确信它们都会为项目做出贡献并添加某些可靠的功能,因为它们经过了预提交钩子来检查它们的有效性。

人类编写的代码存在大量问题,语法和缺失变量只是冰山一角。单元测试(如@NikiC所指出的)起到了很大的作用。开发人员有责任编写可靠、可工作、有文档的代码并进行测试后再提交。使用未声明的变量的愚蠢错误是IDE可以指出的(例如Zend Studio)。你的目标是创建良好的可工作软件,而单元测试是关键。我认为这应该是主要的关注点。有效的php文件只是一个非常宽松的要求...


2

1

哦,没错,你需要的是 PHPUnderControl!它可以检查你的语法,自动检查你的单元测试,进行 C.R.A.P. 指数评估等等。基本上就是超级好用的工具!

快来看看吧,这是它的网址:http://phpundercontrol.org/


0

虽然不是命令行检查器,PHPStorm 一定是最好的IDE之一。

它有各种检查,可以检测到您提到的问题。此外,它会自动重新运行这些检查,检查版本控制中要提交的文件,检查未定义的变量、质量差的代码和“待办事项”。

但是这些检查的问题在于它们不能知道所有情况,所以有时它们会倾向于成为“建议”或“警告”,而不是错误。

但是,它在其所做的事情上非常出色,并且通常可以在您编辑时解决这些问题,因此在任何提交操作之前都能很好地修复错误。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接