Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php Symfony2:如何在服务中注入所有参数?_Php_Service_Configuration_Symfony - Fatal编程技术网

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

Php Symfony2:如何在服务中注入所有参数?,php,service,configuration,symfony,Php,Service,Configuration,Symfony,如何在服务中注入所有参数 我知道我可以做:参数:[%some.key%]这将把参数:some.key:“value”传递给服务结构 我的问题是,如何在服务中注入参数下的所有内容 我需要这个来创建一个导航管理器服务,其中根据不同的设置通过所有配置条目生成不同的菜单/导航/面包屑 我知道我可以注入任意多的参数,但由于它将使用许多参数,并且随着时间的推移会扩展,我认为最好在一开始就传递整个过程 另一种方法可能是,我可以像在控制器$this->container->getParameter('some.

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

我知道我可以做:
参数:[%some.key%]
这将把
参数:some.key:“value”
传递给服务结构

我的问题是,如何在服务中注入
参数下的所有内容

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

我知道我可以注入任意多的参数,但由于它将使用许多参数,并且随着时间的推移会扩展,我认为最好在一开始就传递整个过程

另一种方法可能是,我可以像在控制器
$this->container->getParameter('some.key')中一样获取服务内部的参数,但我认为这与依赖项注入的想法背道而驰


提前谢谢

注意:我知道从设计的角度来看,这个解决方案不是最好的,但它确实起到了作用,所以请避免投反对票。

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

 parameters:
    product.shoppingServiceParams:
        parameter1: 'Some data'
        parameter2: 'some data'
        parameter3: 'some data'
        parameter4: 'some data'
        parameter5: 'some data'
        parameter6: 'some data'
config.yml:

my_service:
    class: MyService\Class
    arguments: [@kernel]
和内部
MyService\Class

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

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

您可以查看缓存目录中的xxxProjectContainer。结果表明,组合参数被直接编译成一个大数组。所以你可以注入容器,然后取出参数。违反法律条文,但不违反法律精神

class MyService {
    public function __construct($container) {
        $this->parameters = $container->parameters; // Then discard container to preclude temptation
我发现我可以做到这一点:

    $container = new \arbiterDevDebugProjectContainer();
    echo 'Parameter Count ' . count($container->parameters) . "\n";
因此,您实际上可以创建一个服务,该服务基本上具有主容器的一个空副本,并注入它以获取参数。必须考虑dev/debug标志,这可能是一个难题


我怀疑您也可以通过编译器传递来完成,但从未尝试过。

我相信您应该单独传递参数。我认为这是通过设计实现的,因此您的服务类不依赖于AppKernel。这样,您就可以在Symfony项目之外重用服务类。在测试服务类时有用的东西。

作为替代方法,您可以通过bundle DI扩展中的Container->getParameterBag将应用程序参数实际注入到服务中

    <?php

    namespace Vendor\ProjectBundle\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 VendorProjectExtension 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');
            /** set params for services */
            $container->getDefinition('my.managed.service.one')
                    ->addMethodCall('setContainerParams', array($container->getParameterBag()->all()));
            $container->getDefinition('my.managed.service.etc')
                    ->addMethodCall('setContainerParams', array($container->getParameterBag()->all()));

        }
}

将整个容器注入到服务中不是一个好做法。此外,如果您有许多服务所需的参数,那么将它们逐一注入到您的服务中是不好的。相反,我使用以下方法:

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

 parameters:
    product.shoppingServiceParams:
        parameter1: 'Some data'
        parameter2: 'some data'
        parameter3: 'some data'
        parameter4: 'some data'
        parameter5: 'some data'
        parameter6: 'some data'
2) 然后我将此根参数注入到我的服务中,如下所示:

services:
  product.shoppingService:
    class: Saman\ProductBundle\Service\Shopping
    arguments: [@translator.default, %product.shoppingServiceParams%]
3) 在五月服务中,我可以访问以下参数:

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;
    }  
}
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'

建议在services.yml上定义一个服务,它将注入参数包并允许访问您的任何参数

service.container_parameters:
  public: false
  class: stdClass
  factory_service: service_container
  factory_method: getParameterBag
注入您的服务,您可以使用下面的

$parameterService->get('some.key');

另一个变体是如何轻松获取参数-您只需将ParameterBag设置为您的服务。您可以用不同的方式来实现它——通过参数或set方法。让我用set方法展示我的示例

因此,在services.yml中,您应该添加如下内容:

my_service:
    class: MyService\Class
    calls:
        - [setParameterBag, ["@=service('kernel').getContainer().getParameterBag()"]]
在MyService\class类中,只需添加使用:

use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
并创建两种方法:

/**                                                                                                                                                                      
 * 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);
}
现在你可以在课堂上使用:

$this->getParameter('your_parameter_name');

正是我所需要的,我忘记了内核。非常感谢。哇!我有一个完全不同的问题,你的回答解决了我的问题!注入内核是个坏主意,你应该尽可能少地注入。最好是一个服务除了直接需要的服务/对象之外,不应该知道任何其他信息。在service.yml:
app.my_服务类:MyClass调用:-[setContainer,['@service_container']]
,然后
类MyClass实现containerawareiinterface
并添加方法
公共函数setContainer(ContainerInterface$container=null){$this->container=$container;}
。注入DI$container->getParameterBag()->all()是个坏主意实际上返回我不建议直接注入容器服务,因为它会打破依赖注入的概念。绝对是最好的方法imho!@Saman如果您为未找到的参数返回null,为什么要使用array_key_?isset()将产生相同的结果,只是更快。-否则回答很好。谢谢,是的,你绝对可以写。但是如果我想抛出异常,如果我的参数列表中不存在键,那么我必须使用数组\u键\u存在喷射“所有参数”实际上并不比注入整个容器或内核更好。我将从设计输入参数开始,继续下面提出的解决方案