liip/container-wrapper-bundle

此包已被废弃,不再维护。未建议替代包。

因为妈妈教你不要通过注入一切来搞砸依赖注入。

安装: 1,725

依赖者: 1

建议者: 0

安全: 0

星标: 29

关注者: 47

分支: 1

开放问题: 1

类型:symfony-bundle

1.1.0 2015-10-26 12:37 UTC

This package is not auto-updated.

Last update: 2022-02-01 12:20:13 UTC


README

此包不再维护。如有需要,请随意分叉。

ContainerWrapperBundle

因为不要通过注入一切来搞砸依赖注入。

此包是为那些不喜欢容器注入但被迫使用它的人准备的。它提供了一个可配置的代理容器,仅公开实际容器的一部分,或重新定义某些服务。您可以选择注入此包装器而不是完整容器,从而对组件的依赖关系拥有更细粒度的控制。

1. It provides an abstract ``liip_container_wrapper.service`` service to extend from.

2. It provides a way to easy set default service and parameters to map

3. It can replace itself with an alias to ``service_container`` via a config
   option as long as no service/parameter is mapped to a different id/name

安装

1. Install with Composer

    `php composer.phar require liip/container-wrapper-bundle`

2. Add this bundle to your application's kernel:

    // application/ApplicationKernel.php
    public function registerBundles()
    {
      return array(
          // ...
          new Liip\ContainerWrapperBundle\LiipContainerWrapperBundle(),
          // ...
      );
    }

配置

默认服务和参数可以在应用程序配置中配置。将 disable_optimization 设置为 true 将在所有未使用映射的情况下移除 ContainerWrapper 服务,以使用 service_container 的别名。

# app/config.yml
liip_container_wrapper:
    services:
        templating: acme_hello.templating
    parameters:
        kernel.debug: true
    disable_optimization: %kernel.debug%

servicesparameters 都配置为键值对。键是从该特定 ContainerWrapper 实例可访问的 id 名称。值可以是 true 或不同服务或参数的 id 名称。在非 true 值的情况下,id 名称将映射到另一个 id 名称。

以上例子

// will return an instance of the 'acme_hello.templating' service
$container->get('templating');

// will return an the value of the 'kernel.debug' parameter
$container->getParameter('kernel.debug');

请注意,由于 templating 映射到不同的服务 id,将 disable_optimization 设置为 false 将没有任何效果,因为普通的 Container 实例无法支持为 templating 设置不同的别名。

示例使用

以下 YAML 配置扩展了 liip_container_wrapper.service 抽象服务,以定义一个 acme_hello.container 服务,可以注入替换 Container 实例,限制对在包配置中以及在此配置中定义的服务和参数的访问。

acme_hello.foo.controller:
    class: Acme\HelloBundle\Controller\FooController
    calls:
        - ['setContainer', [ @acme_hello.container ] ]

acme_hello.container:
    parent: liip_container_wrapper.service
    arguments:
        index_0:
            some_service: true

拯救小猫的故事

为什么哦为什么?

是的,为什么有人会麻烦设置一个漂亮的依赖注入容器,然后浪费其所有的好处,只注入整个容器,从而实际上使他们的代码依赖于 DI 容器中配置的几乎所有内容?我敢肯定,上帝每次都会杀死几只小猫...

除了小猫之外,注入容器还会防止对依赖关系的细粒度调整。也就是说,控制器 Blabla 需要注入与控制器 DingDing 不同的模板化服务,但如果你在两处代码中都使用 $this->container->get('templating'),你怎么做?向上帝祈祷不是答案,他正忙着杀死小猫呢。

而且,那些足够疯狂去关心单元测试的人也会很快意识到,将他们想要注入的所有内容都包裹在一个容器模拟对象中,甚至更没有乐趣。

哦,没有经过繁琐步骤的IDE自动补全支持也是注入容器的一个重大遗憾,或者有哪个IDE能解析你的DIC来确定$this->container->get('i_hate_kittens')返回的是什么?

但是,还有许多糟糕的答案,比如懒惰等等,仍然可以注入DIC,但有三条半可接受的理由

  1. 有人编写了有用的代码,但认为强制注入整个DIC是一个很好的主意

  2. 有相当一部分可选依赖,它们并不能通过拆分服务(实际上有两个)来解决,这也是为什么即使是由好人编写的代码也会发生这种情况的原因)。

  3. 你需要注入一个服务,然后服务才能存在,比如Symfony2中的请求服务

但是,等等,还有希望!

在这些情况下,你现在有办法防止小猫咪被杀害了!

相反,你可以使用ContainerWrapper来显式配置你的依赖关系,并将硬编码的服务ID映射回来,以恢复由于没有显式注入依赖而失去的灵活性。

但是,参数!

是的,参数也由包装器处理,尽管它们并没有从延迟加载论点中受益多少,但我猜一旦开发者走上了黑暗的道路,他可能会继续使用DI容器而不是显式注入参数,所以,可能也应该添加参数支持。邪恶在邪恶的道路上如此富有创造力。