PHP依赖注入

Azi*_*ius 10 php dependency-injection

我试图了解依赖注入,我理解它,在大多数情况下.

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

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

任何帮助我指向正确方向的帮助都会非常棒.

ter*_*ško 30

依赖注入!== DIC

人们应该真的不要混淆他们.依赖注入是来自依赖倒置原则的想法.

DIC是"神奇的治疗方法",它承诺允许您使用依赖注入,但在PHP中通常通过打破面向对象编程的所有其他原则来实现.最糟糕的实现往往也将它全部附加到全局状态,通过静态RegistrySingleton.

无论如何,如果你的课程依赖于太多其他课程,那么一般来说,它意味着课堂本身的设计缺陷.你基本上有一个有太多理由改变的课程,因此违反了单一责任原则.

在这种情况下,依赖注入容器将只隐藏底层设计问题.

如果您想了解有关依赖注入的更多信息,我建议您在youtube上观看"Clean Code Talks":


Mic*_*ski 12

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

DI容器可以是由您需要的各种依赖对象构造的对象或数组,它将传递给构造函数并解压缩.

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

// 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)
);
Run Code Online (Sandbox Code Playgroud)

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

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'];
  }
}
Run Code Online (Sandbox Code Playgroud)

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

编辑

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

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

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);
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 这是DIC非常可怕的实现.另外,当您不写入数组时,将数组作为参考传递的重点是什么? (11认同)
  • 这是服务定位器的反模式.谷歌一下. (4认同)
  • 你真的会在构造函数中写入引用的数组吗?那太疯狂了.或者只是因为你不懂php5中的copy-on-write. (3认同)
  • 不,你不应该.特别是不像你的柴油那样可怕. (2认同)