我们假设我们有一个典型的class DB
来访问数据库,如果这个类是static
我们可以在我们的代码中的任何地方调用它:
DB::execQuery(...);
但是这会产生依赖关系,所以让我们使DB类不是静态的,在这种情况下我们会在代码中的某处:
$db = new DB();
然后我们可以调用我们的代码
$db->execQuery(...);
但现在在$db
内使用function
时,我们需要每次都像这样首次声明
global $db;
有没有办法解决这个问题?
一种方法可能是在使用它的类中注入$db
对象,但是我必须在所有使用它的类中注入它,这是一个可笑的,一个静态类会很多更快地处理和编写更少的代码。我错过了什么吗?!
答案 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业务。
享受重构。