在PHP类方法中使用静态变量是好的

时间:2014-02-03 08:31:37

标签: php codeigniter static dependency-injection

我正在做一个“容器”类来保存我的所有模型/服务实例,该类是一个单例。

考虑以下代码部分(来自CodeIgniter项目):

public function getReviewModel()
{
    static $loaded = false;

    if (!$loaded)
    {
        $this->load->model('review_model');

        $loaded = true;
    }

    return $this->review_model;
}

我想知道是否仍然可以使用这样的静态内部方法,或者我应该只使用类属性(我的意思是性能和编码标准)?

2 个答案:

答案 0 :(得分:2)

在你的例子中,没有什么能阻止程序员多次实例化这个类(带有可怕的结果),所以这是一个令人困惑的代码。

静态变量有其用途,可以是函数的局部变量,也可以是类级定义的 特别是在PHP脚本中,当输出通常是单个数据时,可以方便地作为仅定义静态属性和方法的类来处理。
那将是一个真正的,万无一失的单身人士课程。

由于将静态变量误认为动态变量是一个常见的陷阱,我倾向于偏向静态类变量以避免混淆(即self::$...语法使它们清楚地突出)。

答案 1 :(得分:1)

就PHP中的静态问题而言,普遍的共识是:尽可能避免。是的,99%的情况下,可以避免静力学 应该百分之百地避免单身人士。 For reasons you can find here以及网络上的其他任何地方。单身人士就像共产主义一样:听起来很不错,但是当进行练习时,事实证明你有一两件事没有预料到。
Singletons的主要目标是保留状态,但PHP本身是无状态的,所以在下一个请求中,单例需要重新初始化。

如果我像你一样写吸气剂,我倾向于以一种懒惰的方式创造它们:

class Example
{
    private $reviewModel = null;//create property
    public function getReviewModel()
    {
        if ($this->reviewModel === null)
        {//load once the method is called, the first time
            $this->reviewModel = $this->load->model('review_model');
        }
        return $this->reviewModel;
    }
}

这基本上做同样的事情,不使用静态。因为我正在使用属性,所以我仍然保留实例,因此如果再次调用getReviewModel方法,则会跳过load->model调用,就像使用静态一样。 但是,由于您要询问性能以及编码标准:静态比实例属性稍微慢一些:每个实例都有一个包含其属性的HashTable和一个指向其定义的指针。静态驻留在后者中,因为它们由所有实例共享,因此静态属性需要额外的查找工作:

instance -> HashTable -> property
instance -> definition -> HashTable -> property

这不是完整的故事,check answer + links here,但基本上:通往静态的路线更长。

至于编码标准:它们存在,虽然仍然是非正式的,但大多数主要参与者都订阅它们,所以你应该这样:PHP-FIG
$this->_protectedProperty;之类的东西不符合PSR-2标准,例如,它非常明确地指出:

  

属性名称不应以单个下划线为前缀,以表示受保护或隐私可见性。