从任何地方访问DI容器

时间:2012-09-04 07:57:55

标签: zend-framework dependency-injection

我在Zend Framework项目中实现了Symfony2依赖注入容器,它在我的应用程序的MVC层中运行良好。我已经在我的引导程序中初始化了DIC,并且可以通过调用以下方式访问它:

Zend_Controller_Front::getInstance()->getParam('bootstrap')->getDic()

问题是我的应用程序的某些部分没有使用Zend Framework应用程序/ MVC层。我的CLI工具例如。我可以在那里完美地初始化一个新的DIC,但这只是来自Bootstrap文件的一些复制粘贴工作,这会在路上遇到麻烦(DRY原则等)

这是一个更好的解决方案,让我的DIC在Zend_Registry中可用,或者作为静态方法DIC::getInstance()调用的单例吗?

我知道注册表和单例被认为是坏事,但DIC是应用程序的高级部分,我可能永远不会遇到使它成为坏事的问题。

这是一个很好的解决方案还是有更好的方法来实现全球可访问的DIC?

2 个答案:

答案 0 :(得分:1)

我过去使用Pimple(由Symfony的所有者Fabien Potencier创建)实现了这一目标。

  

Pimple是PHP 5.3的一个小型依赖注入容器,它只包含一个文件和一个类(大约50行代码)。

以下是我将其与我的ZF1应用程序相结合的方法:

  1. 在应用程序的bootstrap中创建一个新的Pimple容器
  2. 使用适当的依赖关系声明所有服务
  3. 通过控制器或CLI工具访问DIC
  4. 通过DIC访问服务
  5. 如果您的服务声明得很好(通过构造函数注入依赖项),则不必访问控制器或CLI工具之外的DIC。

    使用基本控制器类通过$this->container

    轻松访问DIC
    abstract class MyApp_Controller_Action extends Zend_Controller_Action
    {
        protected $container;
    
        public function init()
        {
            $this->container = Zend_Controller_Front::getInstance()
                                   ->getParam('bootstrap')->getDic();
        }
    }
    

    为了将DIC用于CLI工具:

    1. 扩展Zend_Application以创建CLI应用程序
    2. 覆盖run()以阻止MVC堆栈引导
    3. 创建CLI工具时,通过其构造函数
    4. 注入DIC

      使用基本命令类通过$this->container轻松访问DIC:

      abstract class MyApp_Command
      {
          protected $container;
      
          public function __construct($container)
          {
              $this->container = $container;
          }
      }
      

答案 1 :(得分:1)

要在CLI文件中访问引导程序资源,您可以去部分引导应用程序

而不是这样做(public / index.php)并引导整个应用程序:

$application = new Zend_Application(
    APPLICATION_ENV,
    APPLICATION_PATH . '/configs/application.ini'
);
$application->bootstrap()
            ->run();

您可以执行此操作并仅启动所需的资源:

$app = new Zend_Application(
    APPLICATION_ENV,
    APPLICATION_PATH .  '/configs/application.ini'
);

// Selectively bootstrap resources:
$app->bootstrap('db');
$app->bootstrap('log');
$app->bootstrap('autoload');
$app->bootstrap('config');
$app->bootstrap('di');

您必须确保以正确的顺序初始化它们(例如,如果您的日志有数据库写入器,则可能需要在日志记录组件之前加载数据库)。

从那里,您可以调用部分引导程序(对于DI组件,您可以调用$app->getBootstrap()->getContainer()。您可以访问引导程序中可用的所有方法。