【问题标题】:Dependency Injenction in config.ymlconfig.yml 中的依赖注入
【发布时间】:2014-12-12 22:46:40
【问题描述】:

我有两个服务,我想从 config.yml 传递我的参数

我的 config.yml

parameters:
    MyService.class:      Acme\UserBundle\Services\sendEmail
    MyService.arguments:  @mailer

    NewUserListener.class:  Acme\UserBundle\Event\NewUserListener
    NewUserListener.arguments:  @MyService

我在 bundle 中的 service.yml

services:
MyService:
    class:        %MyService.class%
    arguments:    [%MyService.arguments%]

NewUserListener:
    class: %NewUserListener.class%
    arguments:    [%NewUserListener.arguments%]
    tags:
        - { name: kernel.event_listener, event: new.user, method: sendEmailToUsers }

我遇到了一个错误

您不能转储带有包含对参数的引用的容器 其他服务

我的问题是:

  • 如何从 config.yml 注入我的参数?
  • 在哪里可以找到像@mailer 这样的“全球服务”列表?我在文档中找不到

【问题讨论】:

    标签: symfony


    【解决方案1】:

    您不能在参数中引用服务。您应该将%MyService.arguments% 替换为@mailer

    要查找所有可用服务,请运行 php app/console container:debug

    【讨论】:

    • 感谢您的回复。然后当我使用tags: - { name: kernel.event_listener, 时,我的服务被添加到容器中,我可以在php app/console container:debug 中找到它。它可以“随处”使用,对吧?
    • With php app/console container:debug 我可以看到dependency injection container 中的所有服务?
    • 服务总是随处可用。标签使服务成为一个监听器,这完全不同
    【解决方案2】:

    这有点复杂!

    首先,您必须像这样声明您的默认服务(我更改了所有名称以符合 Symfony2 的约定):

    # resources/config/services.yml
    
    services:
        my_own.service.default.class: Acme\UserBundle\Services\sendEmail
        my_own.user_listener.default.class: Acme\UserBundle\Event\NewUserListener
    
    services:
        my_own.service.default:
            class: %my_own.service.default.class%
            arguments: [@mailer]
    
        my_own.user_listener:
            class: %my_own.user_listener.class%
            arguments: [@my_own.service]
            tags:
                - { name: kernel.event_listener, event: new.user, method: sendEmailToUsers }
    

    我们将define some configuration for your bundle 以允许更改使用的服务:

    namespace My\OwnBundle\DependencyInjection;
    
    use Symfony\Component\Config\Definition\Builder\TreeBuilder;
    use Symfony\Component\Config\Definition\ConfigurationInterface;
    
    /**
     * This is the class that validates and merges configuration from your app/config files
     *
     * To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html#cookbook-bundles-extension-config-class}
     */
    class Configuration implements ConfigurationInterface
    {
        /**
         * {@inheritDoc}
         */
        public function getConfigTreeBuilder()
        {
            $treeBuilder = new TreeBuilder();
            $rootNode = $treeBuilder->root('my_own');
    
            // Here you should define the parameters that are allowed to
            // configure your bundle. See the documentation linked above for
            // more information on that topic.
            $rootNode
                ->children()
                    ->scalarNode('service')->defaultValue('my_own.service.default')->end()
                    ->scalarNode('user_listener')->defaultValue('my_own.user_listener.default')->end()
                ->end();
    
            return $treeBuilder;
        }
    }
    

    请注意,默认情况下,我们使用上面在捆绑包中定义的默认服务。

    您现在可以使用以下内容更改您的服务(在您的app/config.yml 中),例如:

    # app/config.yml
    
    my_own:
        service: my_other.service
        user_listener: my_other.user_listener
    

    当然,您可以根据需要在您的包或另一个包中定义服务my_other.servicemy_other.user_listener

    现在我们必须告诉如何使用这个配置来获取想要的服务:

    namespace My\OwnBundle\DependencyInjection;
    
    use Symfony\Component\DependencyInjection\ContainerBuilder;
    use Symfony\Component\Config\FileLocator;
    use Symfony\Component\HttpKernel\DependencyInjection\Extension;
    use Symfony\Component\DependencyInjection\Loader;
    
    /**
     * This is the class that loads and manages your bundle configuration
     *
     * To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html}
     */
    class MyOwnExtension extends Extension
    {
        /**
         * {@inheritDoc}
         */
        public function load(array $configs, ContainerBuilder $container)
        {
            $configuration = new Configuration();
            $config = $this->processConfiguration($configuration, $configs);
    
            $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
            $loader->load('services.yml');
    
            $container->setAlias('my_own.service', $config['service']);
            $container->setAlias('my_own.user_listener', $config['user_listener']);
        }
    }
    

    最后,在其余代码中,您必须在代码中使用别名服务 my_own.servicemy_own.user_listener

    // In one of your controller:
    $this->container->get('my_own.service');
    /* or directly */ $this->get('my_own.service'); // if your controller is a child of the framework bundle class `Controller`.
    

    【讨论】:

    • 谢谢!现在这对我来说很复杂,但在未来,我会尝试这样做
    • 请注意,对于不打算重复使用的捆绑包,这样做没有意义
    • 刚开始学习 Symfony2 中的依赖注入可能会有点困难,但它可以让您编写更具可扩展性和可维护性的代码,并参与 Symfony2 的主要开源包。这是一个有趣的link to learn more about it
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-08
    • 2014-06-12
    • 2013-04-10
    • 2010-11-27
    相关资源
    最近更新 更多