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\"
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:
config.yml:
my_service:
class: MyService\Class
arguments: [@kernel]
And inside MyService\Class
:
public function __construct($kernel)
{
$this->parameter = $kernel->getContainer()->getParameter('some.key');
// or to get all:
$this->parameters = $kernel->getContainer()->getParameterBag()->all();
}
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:
1) In config.yml I define the parameters that I need for my service like this:
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:
services:
product.shoppingService:
class: Saman\ProductBundle\Service\Shopping
arguments: [@translator.default, %product.shoppingServiceParams%]
3) In may service I can access these parameters like:
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
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'
As alternative approach would be that you can actually inject application parameters into your service via Container->getParameterBag in you bundle DI Extension
<?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:
[Symfony\Component\DependencyInjection\Exception\RuntimeException]
Unable to dump a service container if a parameter is an object or a resource.
Tested under Symfony version 2.3.4
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.
So in services.yml you should add something like:
my_service:
class: MyService\Class
calls:
- [setParameterBag, ["@=service('kernel').getContainer().getParameterBag()"]]
and in class MyService\Class just add use:
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
and create 2 methods:
/**
* 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');
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.
Suggestion to define a service at services.yml, which will inject the parameterBag and allow access to any of your parameter
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');