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.

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

报告相同问题?

悬赏问题

  • ¥100 需要跳转番茄畅听app的adb命令
  • ¥50 寻找一位有逆向游戏盾sdk 应用程序经验的技术
  • ¥15 请问有用MZmine处理 “Waters SYNAPT G2-Si QTOF质谱仪在MSE模式下采集的非靶向数据” 的分析教程吗
  • ¥50 opencv4nodejs 如何安装
  • ¥15 adb push异常 adb: error: 1409-byte write failed: Invalid argument
  • ¥15 nginx反向代理获取ip,java获取真实ip
  • ¥15 eda:门禁系统设计
  • ¥50 如何使用js去调用vscode-js-debugger的方法去调试网页
  • ¥15 376.1电表主站通信协议下发指令全被否认问题
  • ¥15 物体双站RCS和其组成阵列后的双站RCS关系验证