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存在喷射“所有参数”实际上并不比注入整个容器或内核更好。我将从设计输入参数开始,继续下面提出的解决方案