避免使用对Exception的静态访问


Avoid using static access to Exception

我刚刚第一次启动PHPMD,不出所料,我遇到了一个无法解决的错误。错误为

避免在中使用对类"InvalidArgumentException"的静态访问方法"setLang"。

代码是

public function setLang($val0) {
    switch ($val0) {
    case ENG:
    case FRE:
    case SPA;
        $this->lang = $val0;
        break;
    default:
        throw new InvalidArgumentException("Invalid language choice.");
    }
}

我尝试了各种不同的方法,但我认为Exception最终是一个静态工厂(???),所以它必须具有静态访问权限。但是,PHPMD的人肯定比我聪明,所以这不会让他们担心。

为什么存在此警告,以及如何解决?

此警告背后的思想是,如果使用new关键字将类名嵌入到代码中,则很难在测试中交换这些类以及被测试代码可能调用的mock或stub方法。请参阅PHPMD规则中的说明。

我认为在您的情况下,这是误报,因为异常通常本身没有太多行为,但它们的类名(及其背后的类层次结构)几乎是它们唯一重要的东西。

如果你想去掉这里的警告,你可以在这里使用@SupressWarnings注释。

啊,经过一番挖掘,我直接从马嘴里找到了答案。

在位于yourphpdir'data'PHP_PMD'resources'rulesets的配置文件中,cleancode.xml具有CDATA注释,用于解释设置。

这个上面写着:

静态访问导致对其他类和导致难以测试代码。不惜一切代价避免使用静态访问而是通过构造函数注入依赖项。唯一的案例当静态访问可接受时,是用于工厂方法时。

解决它的方法就是将异常作为参数传递,这样它就在类之外声明了。

$foo->setLang("Oh noes!", new InvalidArgumentException("No lang for you."));

因为我使用了很多self::作为常量,所以更改phpmd代码以接受self:和parent:。

在第36行的PHP/PMD/Rule/CleanCode/StaticAccess.PHP程序中,更改为:

if ($this->isReferenceInParameter($reference)
    || $reference->getImage() === 'self' 
    || $reference->getImage() === 'parent' 
    ) {
    continue;
}

也许您可以使用它来完善代码。

如果使用XML规则集,则可以从此规则中排除某些类(完整命名空间):

    <rule ref="rulesets/cleancode.xml">
        <exclude name="StaticAccess"/>
    </rule>
    <rule ref="rulesets/cleancode.xml/StaticAccess">
        <properties>
            <property name="exceptions" value="'Drupal'views'Views,'Drupal'Core'Access'AccessResult" />
        </properties>
    </rule>