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 pyqt6如何引用qrc文件加载里面的的资源
  • ¥15 安卓JNI项目使用lua上的问题
  • ¥20 RL+GNN解决人员排班问题时梯度消失
  • ¥15 统计大规模图中的完全子图问题
  • ¥15 使用LM2596制作降压电路,一个能运行,一个不能
  • ¥60 要数控稳压电源测试数据
  • ¥15 能帮我写下这个编程吗
  • ¥15 ikuai客户端l2tp协议链接报终止15信号和无法将p.p.p6转换为我的l2tp线路
  • ¥15 phython读取excel表格报错 ^7个 SyntaxError: invalid syntax 语句报错
  • ¥20 @microsoft/fetch-event-source 流式响应问题