PHP避免使用静态类来避免依赖,但我需要在任何地方使用全局

时间:2012-05-07 17:07:21

标签: php static global-variables global static-classes

我多次听说避免静态类因为they will insert dependencies that will render your code unusable in other projects, and will not allow to unit test it

我们假设我们有一个典型的class DB来访问数据库,如果这个类是static我们可以在我们的代码中的任何地方调用它:

DB::execQuery(...);

但是这会产生依赖关系,所以让我们使DB类不是静态的,在这种情况下我们会在代码中的某处:

$db = new DB();

然后我们可以调用我们的代码

$db->execQuery(...);

但现在在$db内使用function时,我们需要每次都像这样首次声明

global $db;

有没有办法解决这个问题?

一种方法可能是在使用它的类中注入$db对象,但是我必须在所有使用它的类中注入它,这是一个可笑的,一个静态类会很多更快地处理和编写更少的代码。我错过了什么吗?!

2 个答案:

答案 0 :(得分:5)

可以在实例化到属性时注入$ db,然后您只需要访问此属性而不是将其传递给每个方法。

class MyClass {
  protected $_db; // DB Connection
  public function __construct($db) {
    $this->_db = $db;
  }

  public function foo() {
    $this->_db->query('...');
  }

}

除此之外,你可以考虑使用一个服务容器(也称为依赖注入容器),它可以像一个全局变量一样运行,但可以解决一些测试问题。看看其中一些相关问题

使用DI容器可以在类DI_Container::get('db')等类中使用静态方法。它看起来很像global或其他一些静态调用..但在这种情况下DI_Container包含允许在测试和其他情况下采取额外操作的特殊方法..消除了一些全球的“邪恶”。

答案 1 :(得分:1)

除了Mike B的回答,我还要指出代码中的错误设计是:“我们可以在代码中的任何地方调用它。”

实际上,数据库只应由您的模型使用,或者您的应用程序的一小部分必须知道数据库。所以这些类应该知道有一个数据库,并将其用作依赖项(如Mike B所说,通过构造函数传递)。

但是你的应用程序的其余部分应该不关心数据库,它应该只关心模型。专注于重构并将访问数据库的所有代码收集到Model类中。

这样,您的应用程序将具有一个具有依赖关系的Model层:数据库对象/连接。您的应用程序的其余部分将使用模型,无论在模型中发生什么,无论是Controller / View业务。

享受重构。