duanchuang6978 2017-12-19 16:59
浏览 42
已采纳

如何使用Pimple for Dependency Injection在另一个类中最好地使用对象工厂?

I am still trying to wrap my head around some of the aspects of the Dependency Injection design pattern using Pimple. I completely get the concept of using a constructor or setter function belonging to class Foo to establish it's dependency on class Bar.

The part I don't quite get is how to properly instantiate multiple new instances of class Bar from inside a method belonging to Foo while using a Pimple factory.

Basically I want to accomplish the equivalent of this:

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;
     }

}

I am using Pimple for my container like so:

bootstrap.php

$container = new Container();

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

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

The idea is that there can be multiple pages defined, and each page is potentially comprised of multiple blocks. The properties for each block are defined by methods within Page. And it needs to happen using entirely decoupled code.

It is my understanding that injecting the entire container into Page as a dependency is actually the Service Locator anti-pattern. So the following is BAD code:

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;
     }

}

How do I go about giving Page the ability to use the Block factory that is defined in the DIC?

  • 写回答

1条回答 默认 最新

  • dongzai0020 2017-12-24 21:19
    关注

    So, in your DI container setup, you can pass around container references. So if you have the need to use the Block class a lot in your page class, you could do this:

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

    But this means you must add a parameter to your Page class's constructor:

    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;
         }
    
    }
    

    So, we're not actually passing the entire container into each class, but rather allowing the DI container to pass objects as needed.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 程序不包含适用于入口点的静态Main方法
  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记