PHP 依赖注入

2021-12-26 00:00:00 dependency-injection php

我正在努力了解依赖注入,并且在很大程度上我理解它.

I'm trying to get my head around Dependency Injection and I understand it, for the most part.

但是,假设由于某种原因,我的一个类依赖于多个类,而不是在构造函数中将所有这些都传递给这个类,是否有更好、更明智的方法?

However, say if, for some reason, one of my classes was dependent on several classes, instead of passing all of these to this one class in the constructor, is there a better, more sensible method?

我听说过 DI Containers,这是我解决这个问题的方式吗?我应该从哪里开始这个解决方案?我是否将依赖项传递给我的 DIC,然后将其传递给需要这些依赖项的类?

I've heard about DI Containers, is this how I would go about solving this problem? Where should I start with this solution? Do I pass the dependencies to my DIC, and then pass this to the class that needs these dependencies?

任何能帮我指明正确方向的帮助都会很棒.

Any help that would point me in the right direction would be fantastic.

推荐答案

如果您有多个依赖项需要处理,那么 DI 容器可以成为解决方案.

If you have several dependencies to deal with, then yes a DI container can be the solution.

DI 容器可以是由您需要的各种依赖对象构成的对象或数组,这些对象会被传递给构造函数并解包.

The DI container can be an object or array constructed of the various dependent object you need, which gets passed to the constructor and unpacked.

假设您需要一个配置对象、一个数据库连接和一个传递给每个类的客户端信息对象.您可以创建一个包含它们的数组:

Suppose you needed a config object, a database connection, and a client info object passed to each of your classes. You can create an array which holds them:

// Assume each is created or accessed as a singleton, however needed...
// This may be created globally at the top of your script, and passed into each newly
// instantiated class
$di_container = array(
  'config' = new Config(),
  'db' = new DB($user, $pass, $db, $whatever),
  'client' = new ClientInfo($clientid)
);

并且您的类构造函数接受 DI 容器作为参数:

And your class constructors accept the DI container as a parameter:

class SomeClass {
  private $config;
  private $db;
  private $client;
 
  public function __construct(&$di_container) {
    $this->config = $di_container['config'];
    $this->db = $di_container['db'];
    $this->client = $di_container['client'];
  }
}

代替我上面所做的数组(这很简单),您还可以将 DI 容器创建为一个类本身,并使用单独注入其中的组件类对其进行实例化.使用对象而不是数组的一个好处是,默认情况下它将通过引用传递给使用它的类,而数组是通过值传递的(尽管数组中的对象仍然是引用).

Instead of an array as I did above (which is simple), you might also create the DI container as an class itself and instantiate it with the component classes injected into it individually. One benefit to using an object instead of an array is that by default it will be passed by reference into the classes using it, while an array is passed by value (though objects inside the array are still references).

对象在某些方面比数组更灵活,尽管最初的编码更复杂.

There are some ways in which an object is more flexible than an array, although more complicated to code initially.

容器对象也可以在其构造函数中创建/实例化包含的类(而不是在外部创建它们并将它们传入).这可以为使用它的每个脚本节省一些编码,因为您只需要实例化一个对象(它本身实例化其他几个).

The container object may also create/instantiate the contained classes in its constructor as well (rather than creating them outside and passing them in). This can save you some coding on each script that uses it, as you only need to instantiate one object (which itself instantiates several others).

Class DIContainer {
  public $config;
  public $db;
  public $client;

  // The DI container can build its own member objects
  public function __construct($params....) {
    $this->config = new Config();

    // These vars might be passed in the constructor, or could be constants, or something else
    $this->db = new DB($user, $pass, $db, $whatever);

    // Same here -  the var may come from the constructor, $_SESSION, or somewhere else
    $this->client = new ClientInfo($clientid);
  }
}

相关文章