Symfony2:如何在服务中注入所有参数?

Ton*_*nov 27 php service configuration symfony

如何在服务中注入所有参数?

我知道我可以这样做:arguments: [%some.key%]哪个会传递parameters: some.key: "value"给服务__construct.

我的问题是,如何注入服务中的所有内容parameters

我需要这个来制作导航管理器服务,其中根据不同的设置通过所有配置条目生成不同的菜单/导航/面包屑.

我知道我可以按照自己的意愿注入尽可能多的参数,但由于它会使用其中的一些参数并随着时间的推移而扩展,我认为最好在开始时将整个事情传递给我.

其他的方法可能是,如果我能得到你可以在控制器里做服务里面的参数$this -> container -> getParameter('some.key');,但我认为这将是对依赖注入的想法?

提前致谢!

Sam*_*igh 48

将整个Container注入服务并不是一个好习惯.此外,如果您的服务需要许多参数,那么将所有这些参数逐个注入您的服务并不好.相反,我使用这种方法:

1)在config.yml中我定义了我的服务所需的参数,如下所示:

 parameters:
    product.shoppingServiceParams:
        parameter1: 'Some data'
        parameter2: 'some data'
        parameter3: 'some data'
        parameter4: 'some data'
        parameter5: 'some data'
        parameter6: 'some data'
Run Code Online (Sandbox Code Playgroud)

2)然后我将这个root参数注入我的服务,如:

services:
  product.shoppingService:
    class: Saman\ProductBundle\Service\Shopping
    arguments: [@translator.default, %product.shoppingServiceParams%]
Run Code Online (Sandbox Code Playgroud)

3)在may服务中我可以访问以下参数:

namespace Saman\ProductBundle\Service;

use Symfony\Bundle\FrameworkBundle\Translation\Translator;

class Shopping
{   
    protected $translator;
    protected $parameters;

    public function __construct(
        Translator $translator, 
        $parameters
        ) 
    {
        $this->translator = $translator;
        $this->parameters = $parameters;
    }

    public function dummyFunction()
    {
        var_dump($this->getParameter('parameter2'));
    }

    private function getParameter($key, $default = null)
    {
        if (isset($this->parameters[$key])) {
            return $this->parameters[$key];
        }

        return $default;
    }  
}
Run Code Online (Sandbox Code Playgroud)

4)我还可以为不同的环境设置不同的值.例如在config_dev.yml中

 parameters:
    product.shoppingServiceParams:
        parameter1: 'Some data for dev'
        parameter2: 'some data for dev'
        parameter3: 'some data for dev'
        parameter4: 'some data for dev'
        parameter5: 'some data for dev'
        parameter6: 'some data'
Run Code Online (Sandbox Code Playgroud)

  • 绝对是最好的方法imho! (4认同)

Vla*_*ich 11

另一个变量如何轻松获取参数 - 您只需将ParameterBag设置为您的服务即可.你可以通过不同的方式 - 通过参数或通过set方法.让我用set方法展示我的例子.

所以在services.yml中你应该添加如下内容:

my_service:
    class: MyService\Class
    calls:
        - [setParameterBag, ["@=service('kernel').getContainer().getParameterBag()"]]
Run Code Online (Sandbox Code Playgroud)

并在类MyService\Class中添加use:

use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
Run Code Online (Sandbox Code Playgroud)

并创建2个方法:

/**                                                                                                                                                                      
 * Set ParameterBag for repository                                                                                                                                       
 *                                                                                                                                                                       
 * @param ParameterBagInterface $params                                                                                                                                  
 */
public function setParameterBag(ParameterBagInterface $params)
{
    $this->parameterBag = $params;
}

/**                                                                                                                                                                      
 * Get parameter from ParameterBag                                                                                                                                       
 *                                                                                                                                                                       
 * @param string $name                                                                                                                                                   
 * @return mixed                                                                                                                                                        
 */
public function getParameter($name)
{
    return $this->parameterBag->get($name);
}
Run Code Online (Sandbox Code Playgroud)

现在你可以在课堂上使用:

$this->getParameter('your_parameter_name');
Run Code Online (Sandbox Code Playgroud)


dan*_*son 8

我相信你应该单独传递参数.我认为它是按照设计进行的,所以你的服务类不依赖于AppKernel.这样您就可以在Symfony项目之外重用您的服务类.在测试服务类时有用的东西.


Cer*_*rad 7

AppKernel可以工作,但它比注入容器更糟糕(从范围的角度来看),因为内核中有更多东西.

您可以在缓存目录中查看xxxProjectContainer.事实证明,各种参数作为一个大数组直接编译成它.所以你可以注入容器然后拔出参数.违反法律条文,但违反法律精神.

class MyService {
    public function __construct($container) {
        $this->parameters = $container->parameters; // Then discard container to preclude temptation
Run Code Online (Sandbox Code Playgroud)

只是搞乱了我发现我可以做到这一点:

    $container = new \arbiterDevDebugProjectContainer();
    echo 'Parameter Count ' . count($container->parameters) . "\n";
Run Code Online (Sandbox Code Playgroud)

因此,您实际上可以创建一个基本上是主容器的空副本的服务,并将其注入以获取参数.必须考虑可能很痛苦的开发/调试标志.

我怀疑你也可以用编译器传递来做但从未尝试过.

  • 我不建议直接注入容器服务,因为它会打破依赖注入的概念. (4认同)

Ant*_*nko 5

注意:我知道这个解决方案从设计的角度来看并不是最好的,但是它可以完成工作,所以请避免投票.

您可以注入\ AppKernel对象,然后访问所有参数,如下所示:

config.yml:

my_service:
    class: MyService\Class
    arguments: [@kernel]
Run Code Online (Sandbox Code Playgroud)

内部MyService\Class:

public function __construct($kernel)
{
    $this->parameter = $kernel->getContainer()->getParameter('some.key');
    // or to get all:
    $this->parameters = $kernel->getContainer()->getParameterBag()->all();
}
Run Code Online (Sandbox Code Playgroud)

  • 注入内核的坏主意 (39认同)
  • 实际上,你应尽量少注射.优选地,服务应该永远不知道除了它直接需要的服务/对象之外的任何事情. (2认同)