问题描述
我多次听到避免使用静态类,因为他们会插入依赖项,导致代码不可用其他项目,并且不允许单元测试它。。
假设我们有一个典型的 class DB 访问数据库,如果这个类是 static ,我们可以在代码中调用它:
DB ::使用ExecQuery(...);
但是这会产生依赖关系,所以我们让DB类不是静态的,在这种情况下,我们会有某个地方在我们的代码中:
$ db = new DB();
然后我们可以调用我们的代码
$ DB->使用ExecQuery(...);
但现在当使用里面的 $ db 时一个函数我们需要每次首先声明它像这样
global $ db;
是否有解决此问题的方法?
<一种方法可能是在使用它的类中注入 $ db 对象,但是我必须将其注入到所有使用它的类中,这是荒谬的,静态类会更快,而且编写代码更少。我错过了什么?!
$ db可以在实例化时注入到一个属性中,那么您只需要访问而不是传递给每个方法。
class MyClass {
protected $ _db; // DB连接
public function __construct($ db){
$ this-> _db = $ db;
public function foo(){
$ this-> _db-> query('...');
}
}
除此之外,您可以查看拥有一个服务容器(又名依赖注入容器),它可以像全局变量那样工作,但可以解决一些测试问题。看看这些相关的问题
拥有一个DI容器可以让你在你的类中使用静态方法,比如 DI_Container ::的get( 'DB')。它看起来很像 global 或其他一些静态调用..但在这种情况下, DI_Container 包含特殊方法允许在测试和其他情况下采取额外的行动..消除一些全球性的恶性。
Many times I heard to avoid static classes because they will insert dependencies that will render your code unusable in other projects, and will not allow to unit test it.
Let's say we have a typical class DB to access the Data Base, if such class is static we could call it wherever in our code:
DB::execQuery(...);
but this creates dependencies, so let's make the DB class NOT static, in such case we would have somewhere in our code:
$db = new DB();
and then we could call in our code
$db->execQuery(...);
But now when using the $db inside a function we need each time to first declare it like this
global $db;
Is there a way to workaround this?
One way could be to inject the $db object in the class that uses it, but I would have to inject it in all classes that use it, that's ridicolous, a static class would be much quicker to work with and less code to write. Am I missing something?!
$db could be injected upon instantiation into a property, then you would only need to access this property instead of passing it around to each method.
class MyClass { protected $_db; // DB Connection public function __construct($db) { $this->_db = $db; } public function foo() { $this->_db->query('...'); } }
Beyond that, you can look into having a service-container (aka dependency-injection container) that trys to act like a global variable but solves some of the testing issues. Take a look at some of these related questions
- If Singletons are bad then why is a Service Container good?
- Is it good practice to have DI container replace a global $registry object?
Having a DI container lets you use static methods in your classes like DI_Container::get('db'). It looks a lot like global or some of the other static calls.. but in this case DI_Container contains special methods that allow for extra actions to be taken during testing and other circumstances.. eliminating some of the 'evilness' of global.
这篇关于PHP避免静态类来避免依赖,但我需要在全球各地使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!