如何在PHP中使用codesniffer检测对象上的动态声明字段

Kas*_*asi 8 php codesniffer magic-methods getter-setter phpcodesniffer

在重构之后,我们在其中一个类中有类似的东西:

class FooBar
{
    // $foo was $bla before
    private $foo;

    public function setBlubbOnArrayOnlyOnce($value)
    {
        // $this->bla was forgotten during refactoring. Must be $this->foo
        if(!isset($this->bla['blubb'])) {
             $this->foo['blubb'] = $value;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

所以最后$ this-> foo ['blubb']总是被设定,不仅一次.这是因为PHP的神奇方法.我们不希望它可以动态访问字段,所以我想我只是添加了一个代码不一致的规则.但我没有发现任何问题,并问我原因.

PHPStorm显示了一个动态通知的字段,但我想在部署周期中使用代码(或类似的东西)自动失败.

有人对此有所了解吗?有一个很好的规则吗?我应该写自己的,怎么样?或者禁用它是不好的做法?

免责声明:我们使用测试,但有时你会错过一些东西......首先要防止这种情况.另外,请不要想出覆盖魔法的方法.我不想在每个班级都有任何特质/抽象.

Dee*_*eep 2

这不是 codeniffer 或 phpstorm 问题。您不可能希望使用 codeniffer 或 IDE 来解决这个问题。IDE、codesniffer、phpdocumentor 等——这是“静态”分析。对于动态分析,您可以使用例如 phpunit。

如果您想检查属性是否存在,则必须使用 property_exists() 函数。

class X
{
    public function __get($name)
    {
        $this->{$name} = null;
        return $this->{$name};
    }
}

$x = new X();
var_dump(property_exists($x, 'foo')); // false
var_dump($x->foo); // NULL
var_dump(property_exists($x, 'foo')); // true
Run Code Online (Sandbox Code Playgroud)

或者您可以对属性使用反射http://php.net/manual/en/class.reflectionproperty.php

如果您想检查“isset”,您必须知道:

var_dump(isset($x), $x); // false + NULL with notice
$x = null;
var_dump(isset($x), $x); // false + NULL
unset($x);
var_dump(isset($x), $x); // false + NULL without notice
Run Code Online (Sandbox Code Playgroud)

当您确定这种情况下的检查时,您可以使用 isset()

但您应该首先检查是否存在财产。否则,您的代码可能会出现未定义的行为。