php Symfony2:如何在服务中注入所有参数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9299981/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Symfony2: How to inject ALL parameters in a service?
提问by Tony Bogdanov
How can I inject ALL parameters in a service?
如何在服务中注入所有参数?
I know I can do: arguments: [%some.key%]
which will pass the parameters: some.key: "value"
to the service __construct.
我知道我可以做到:arguments: [%some.key%]
它将传递parameters: some.key: "value"
给服务 __construct。
My question is, how to inject everything that is under parameters
in the service?
我的问题是,如何注入服务中的所有内容parameters
?
I need this in order to make a navigation manager service, where different menus / navigations / breadcrumbs are to be generated according to different settings through all of the configuration entries.
我需要这个来制作导航管理器服务,其中将根据所有配置条目的不同设置生成不同的菜单/导航/面包屑。
I know I could inject as many parameters as I want, but since it is going to use a number of them and is going to expand as time goes, I think its better to pass the whole thing right in the beginning.
我知道我可以注入任意数量的参数,但是由于它将使用其中的一些参数并且会随着时间的推移而扩展,我认为最好在一开始就传递整个事情。
Other approach might be if I could get the parameters inside the service as you can do in a controller $this -> container -> getParameter('some.key');
, but I think this would be against the idea of Dependency Injection?
其他方法可能是,如果我可以像在控制器中那样获取服务中的参数$this -> container -> getParameter('some.key');
,但我认为这与依赖注入的想法背道而驰?
Thanks in advance!
提前致谢!
采纳答案by Anton Babenko
Note: I know that this solution is not BEST from design point of view, but it does the job, so please avoid down-voting.
注意:我知道从设计的角度来看这个解决方案不是最好的,但它可以完成工作,所以请避免投票。
You can inject \AppKernel object and then access all parameters like this:
您可以注入 \AppKernel 对象,然后像这样访问所有参数:
config.yml:
配置文件:
my_service:
class: MyService\Class
arguments: [@kernel]
And inside MyService\Class
:
里面MyService\Class
:
public function __construct($kernel)
{
$this->parameter = $kernel->getContainer()->getParameter('some.key');
// or to get all:
$this->parameters = $kernel->getContainer()->getParameterBag()->all();
}
回答by Saman Shafigh
It is not a good practice to inject the entire Container into a service. Also if you have many parameters that you need for your service it is not nice to inject all of them one by one to your service. Instead I use this method:
将整个 Container 注入到服务中并不是一个好习惯。此外,如果您的服务需要许多参数,那么将所有参数一一注入到您的服务中并不好。相反,我使用这种方法:
1) In config.yml I define the parameters that I need for my service like this:
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) Then I inject this root parameter to my service like:
2)然后我将此根参数注入到我的服务中,例如:
services:
product.shoppingService:
class: Saman\ProductBundle\Service\Shopping
arguments: [@translator.default, %product.shoppingServiceParams%]
3) In may service I can access these parameters like:
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;
}
}
4) I can also set different values for different environments. For example in config_dev.yml
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'
回答by Vladimir Gilevich
Another variant how to get parameters easy - you can just set ParameterBag to your service. You can do it in different ways - via arguments or via set methods. Let me show my example with set method.
另一个如何轻松获取参数的变体 - 您只需将 ParameterBag 设置为您的服务。您可以通过不同的方式来实现 - 通过参数或通过 set 方法。让我用 set 方法展示我的例子。
So in services.yml you should add something like:
所以在 services.yml 你应该添加如下内容:
my_service:
class: MyService\Class
calls:
- [setParameterBag, ["@=service('kernel').getContainer().getParameterBag()"]]
and in class MyService\Class just add use:
并在 MyService\Class 类中添加使用:
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
and create 2 methods:
并创建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);
}
and now you can use in class:
现在你可以在课堂上使用:
$this->getParameter('your_parameter_name');
回答by dan-klasson
I believe you're supposed to pass the parameters individually. I think it's made that way by design so your service class is not dependent on the AppKernel. That way you can reuse your service class outside your Symfony project. Something that is useful when testing your service class.
我相信你应该单独传递参数。我认为它是这样设计的,因此您的服务类不依赖于 AppKernel。这样你就可以在你的 Symfony 项目之外重用你的服务类。测试服务类时有用的东西。
回答by Cerad
AppKernel would work but it's even worse (from a scope perspective) than injecting the container since the kernel has even more stuff in it.
AppKernel 可以工作,但它比注入容器更糟糕(从范围的角度来看),因为内核中有更多的东西。
You can look at xxxProjectContainer in your cache directory. Turns out that the assorted parameters are compiled directly into it as a big array. So you could inject the container and then just pull out the parameters. Violates the letter of the law but not the spirit of the law.
您可以查看缓存目录中的 xxxProjectContainer。原来,各种参数被直接编译成一个大数组。所以你可以注入容器,然后拉出参数。违反法律条文,但不违反法律精神。
class MyService {
public function __construct($container) {
$this->parameters = $container->parameters; // Then discard container to preclude temptation
And just sort of messing around I found I could do this:
我发现我可以这样做:
$container = new \arbiterDevDebugProjectContainer();
echo 'Parameter Count ' . count($container->parameters) . "\n";
So you could actually create a service that had basically a empty copy of the master container and inject it just to get the parameters. Have to take into account the dev/debug flags which might be a pain.
因此,您实际上可以创建一个服务,该服务基本上具有主容器的空副本,并将其注入以获取参数。必须考虑可能会很痛苦的开发/调试标志。
I suspect you could also do it with a compiler pass but have never tried.
我怀疑您也可以通过编译器传递来做到这一点,但从未尝试过。
回答by ravindrakhokharia
Suggestion to define a service at services.yml, which will inject the parameterBag and allow access to any of your parameter
建议在 services.yml 定义一个服务,它将注入 parameterBag 并允许访问您的任何参数
service.container_parameters:
public: false
class: stdClass
factory_service: service_container
factory_method: getParameterBag
Inject your service, and u can get your parameter using below
注入您的服务,您可以使用下面的参数获取您的参数
$parameterService->get('some.key');
回答by andrew
As alternative approach would be that you can actually inject application parameters into your service via Container->getParameterBag in you bundle DI Extension
作为替代方法,您实际上可以通过捆绑 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()));
}
}
Please note that we can not inject ParameterBag object directly, cause it throws:
请注意,我们不能直接注入 ParameterBag 对象,因为它会抛出:
[Symfony\Component\DependencyInjection\Exception\RuntimeException]
Unable to dump a service container if a parameter is an object or a resource.
[Symfony\Component\DependencyInjection\Exception\RuntimeException]
如果参数是对象或资源,则无法转储服务容器。
Tested under Symfony version 2.3.4
在 Symfony 2.3.4版下测试