在PHP中有处理静态成员的最佳实践吗?


Are there best practices for working with static members in PHP?

PHP允许使用静态成员函数和变量,从5.3开始包括后期静态绑定:

class StaticClass {
    public static $staticVar;
    ...
}
$o = new StaticClass();

目前,有不同的选项来访问这些静态成员:

$o->staticVar;  // as instance variable/ function
$o::staticVar;  // as class variable/ function

还有其他选项可以从类内部访问成员:

self::$staticVar;   // explicitly showing static usage of variable/ function
static::$staticVar; // allowing late static binding

重组一些现有的类,使一些使用静态成员我问自己,如果有最好的做法与静态成员在PHP工作?

显然,它们的作用各不相同。

$o->staticVar

这是无效的,因为您不能/不应该使用实例属性语法访问静态属性。

StaticClass::$staticVar

这很明显地访问了一个特定类上的特定静态变量。

$o::$staticVar

这将访问$o作为实例的类上的静态变量。它主要用作前一种方法的简写,并且在所有方面都是等效的。显然,使用哪个类完全取决于$o是哪个类的实例。

self::$staticVar

只能在类中使用,并且总是指向编写它的类。如果类引用自己,在类中使用这个而不是StaticClass::$staticVar是一个好主意,因为如果以后更改类名,您不需要担心任何事情。例如:

class Foo {
    protected static $bar = 42;
    public function baz() {
        self::$bar;  // good
        Foo::$bar    // the same, but should be avoided because it repeats the class name
    }
}
static::$staticVar

这也只能在类中使用,与上面的self基本相同,但使用晚期静态绑定解决,因此可能引用子类。

什么是"最佳实践"是有争议的。我想说你应该尽可能地具体,但仅此而已。$o::$staticVarstatic::$staticVar都允许类在子类中变化,而self::$staticVarStaticClass::$staticVar则不允许。遵循打开/关闭原则,使用前者是一个好主意,更多的变量方法允许扩展。

属性,无论是静态的还是非静态的,也不应该是public以免破坏封装。

请参见如何不使用静态静态来破坏您的可测试性

首先,不要使用$this->staticVar。我不确定这是什么时候改变的(我相信是PHP 5.4),但在最近的版本中,不再可能以这种方式检索静态变量。

至于使用晚期静态绑定,如果不需要就不要使用它。使用它的原因是,如果您计划使用继承,并希望在派生类中更改静态变量的值。