如何使用 Pimple 进行依赖注入,在另一个 class 中最好地使用一个对象工厂?

How do I best use an object factory inside another class using Pimple for Dependency Injection?

我仍在努力思考使用 Pimple 的依赖注入设计模式的某些方面。我完全理解了使用属于 class Foo 的构造函数或 setter 函数来建立它对 class Bar.

的依赖的概念

我不太明白的部分是如何在使用 Pimple 工厂时从属于 Foo 的方法内部正确实例化 class Bar 的多个新实例。

基本上我想完成相当于这个的:

Block.php

class Block {

     private $filepath;

     public function setFilePath($filepath) {
          $this->filepath = $filepath;
     }

}

Page.php

class Page {

     private function newBlock() {
          //do something here to get $filepath
          $block = new Block();
          $block->setFilePath($filepath);
          return $block;
     }

}

我正在为我的容器使用 Pimple,如下所示:

bootstrap.php

$container = new Container();

$container['page'] = $container->factory(function ($c) {
    return new Page();
});

$container['block'] = $container->factory(function ($c) {
     return new Block();
});

想法是可以定义多个页面,每个页面可能由多个块组成。每个块的属性由 Page 中的方法定义。它需要使用完全分离的代码来实现。

据我了解,将整个容器作为依赖项注入到 Page 实际上是 Service Locator 反模式。所以下面是错误的代码:

class Page {

     private $container;

     public function __construct(Container $container) {
          $this->container = $container;
     }

     private function newBlock() {
          //do something here to get $filepath
          $block = $this->container['block'];
          $block->setFilePath($filepath);
          return $block;
     }

}

如何让 Page 能够使用 DIC 中定义的 Block 工厂?

因此,在您的 DI 容器设置中,您可以传递容器引用。所以如果你需要在你的页面class中大量使用块class,你可以这样做:

$container = new Container();

$container['page'] = $container->factory(function ($c) {
    return new Page( $c['block'] );
});

$container['block'] = $container->factory(function ($c) {
     return new Block();
});

但这意味着您必须向页面 class 的构造函数添加一个参数:

class Page {

    private $block = NULL;

    public function __construct( $block )
    {
      $this->block = $block;
    }

     private function newBlock() {
          //do something here to get $filepath
          $this->block->setFilePath($filepath);
          return $this->block;
     }

}

因此,我们实际上并没有将整个容器传递给每个 class,而是允许 DI 容器根据需要传递对象。