3

很多时候我听说要避免使用静态类,因为它们会插入使您的代码在其他项目中无法使用的依赖项,并且不允许对其进行单元测试

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

DB::execQuery(...);

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

$db = new DB();

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

$db->execQuery(...);

但是现在在使用$dbinside a时function,我们每次都需要先这样声明它

global $db;

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

一种方法是将$db对象注入到使用它的类中,但我必须将它注入到所有使用它的类中,这很荒谬,使用静态类会更快,编写的代码更少。我错过了什么吗?!

4

2 回答 2

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包含允许在测试和其他情况下采取额外操作的特殊方法。消除全局的一些“邪恶”。

于 2012-05-07T17:15:57.523 回答
1

除了 Mike B 的回答之外,我还要指出您代码中的错误设计是:«我们可以在代码中的任何位置调用它»。

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

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

这样,您的应用程序将拥有一个具有依赖关系的模型层:数据库对象/连接。并且您的应用程序的其余部分将使用模型,无论模型中发生什么,都与控制器/视图业务无关。

享受重构。

于 2014-01-28T08:51:22.017 回答